1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 // #define REGISTER_CLEANUP_DEBUG
44 #include "qv4bindings_p.h"
45 #include "qv4program_p.h"
46 #include "qv4compiler_p.h"
47 #include "qv4compiler_p_p.h"
49 #include <private/qqmlglobal_p.h>
50 #include <private/qqmlaccessors_p.h>
51 #include <private/qqmlprofilerservice_p.h>
52 #include <private/qqmlmetatype_p.h>
53 #include <private/qqmltrace_p.h>
54 #include <private/qqmlstringconverters_p.h>
55 #include <private/qqmlproperty_p.h>
57 #include <QtQml/qqmlinfo.h>
58 #include <QtCore/qnumeric.h>
59 #include <QtCore/qmath.h>
60 #include <math.h> // ::fmod
64 using namespace QQmlJS;
68 typedef QQmlRegisterType Type;
70 inline void setUndefined() { dataType = UndefinedType; }
71 inline void setNull() { dataType = NullType; }
72 inline void setNaN() { setnumber(qSNaN()); }
73 inline bool isUndefined() const { return dataType == UndefinedType; }
75 inline void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
76 inline QObject *getQObject() const { return qobjectValue; }
78 inline void setnumber(double v) { numberValue = v; dataType = NumberType; }
79 inline double getnumber() const { return numberValue; }
80 inline double &getnumberref() { return numberValue; }
82 inline void setfloat(float v) { floatValue = v; dataType = FloatType; }
83 inline float getfloat() const { return floatValue; }
84 inline float &getfloatref() { return floatValue; }
86 inline void setint(int v) { intValue = v; dataType = IntType; }
87 inline int getint() const { return intValue; }
88 inline int &getintref() { return intValue; }
90 inline void setbool(bool v) { boolValue = v; dataType = BoolType; }
91 inline bool getbool() const { return boolValue; }
92 inline bool &getboolref() { return boolValue; }
94 inline QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
95 inline QString *getstringptr() { return (QString *)typeDataPtr(); }
96 inline QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
97 inline const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
98 inline const QString *getstringptr() const { return (QString *)typeDataPtr(); }
99 inline const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
101 size_t dataSize() { return sizeof(data); }
102 inline void *typeDataPtr() { return (void *)&data; }
103 inline void *typeMemory() { return (void *)data; }
104 inline const void *typeDataPtr() const { return (void *)&data; }
105 inline const void *typeMemory() const { return (void *)data; }
107 inline Type gettype() const { return dataType; }
108 inline void settype(Type t) { dataType = t; }
110 Type dataType; // Type of data
112 QObject *qobjectValue;
117 void *data[sizeof(QVariant)];
118 qint64 q_for_alignment_1;
119 double q_for_alignment_2;
122 inline void cleanup();
123 inline void cleanupString();
124 inline void cleanupUrl();
125 inline void cleanupColor();
126 inline void cleanupVariant();
128 inline void copy(const Register &other);
129 inline void init(Type type);
130 #ifdef REGISTER_CLEANUP_DEBUG
136 if (dataType >= FirstCleanupType)
137 qWarning("Register leaked of type %d", dataType);
142 void Register::cleanup()
144 if (dataType >= FirstCleanupType) {
145 if (dataType == QStringType) {
146 getstringptr()->~QString();
147 } else if (dataType == QUrlType) {
148 geturlptr()->~QUrl();
149 } else if (dataType == QColorType) {
150 QQml_valueTypeProvider()->destroyValueType(QMetaType::QColor, typeDataPtr(), dataSize());
151 } else if (dataType == QVariantType) {
152 getvariantptr()->~QVariant();
158 void Register::cleanupString()
160 getstringptr()->~QString();
164 void Register::cleanupUrl()
166 geturlptr()->~QUrl();
170 void Register::cleanupColor()
172 QQml_valueTypeProvider()->destroyValueType(QMetaType::QColor, typeDataPtr(), dataSize());
176 void Register::cleanupVariant()
178 getvariantptr()->~QVariant();
182 void Register::copy(const Register &other)
185 if (other.dataType >= FirstCleanupType) {
186 if (other.dataType == QStringType)
187 new (getstringptr()) QString(*other.getstringptr());
188 else if (other.dataType == QUrlType)
189 new (geturlptr()) QUrl(*other.geturlptr());
190 else if (other.dataType == QColorType)
191 QQml_valueTypeProvider()->copyValueType(QMetaType::QColor, other.typeDataPtr(), typeDataPtr(), dataSize());
192 else if (other.dataType == QVariantType)
193 new (getvariantptr()) QVariant(*other.getvariantptr());
197 void Register::init(Type type)
200 if (dataType >= FirstCleanupType) {
201 if (dataType == QStringType)
202 new (getstringptr()) QString();
203 else if (dataType == QUrlType)
204 new (geturlptr()) QUrl();
205 else if (dataType == QColorType)
206 QQml_valueTypeProvider()->initValueType(QMetaType::QColor, typeDataPtr(), dataSize());
207 else if (dataType == QVariantType)
208 new (getvariantptr()) QVariant();
212 } // end of anonymous namespace
214 QV4Bindings::QV4Bindings(const char *programData,
215 QQmlContextData *context,
217 : subscriptions(0), program(0), dataRef(0), bindings(0)
219 program = (QV4Program *)programData;
221 if (dataRef) dataRef->addref();
224 subscriptions = new Subscription[program->subscriptions];
225 bindings = new Binding[program->bindings];
227 QQmlAbstractExpression::setContext(context);
231 QV4Bindings::~QV4Bindings()
234 delete [] subscriptions; subscriptions = 0;
235 if (dataRef) dataRef->release();
238 QQmlAbstractBinding *QV4Bindings::configBinding(int index, QObject *target,
239 QObject *scope, int property,
240 int line, int column)
242 Binding *rv = bindings + index;
245 rv->property = property;
252 addref(); // This is decremented in Binding::destroy()
257 void QV4Bindings::Binding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
262 if (e) update(flags);
266 void QV4Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
268 parent->run(this, flags);
271 void QV4Bindings::Binding::destroy()
280 int QV4Bindings::Binding::propertyIndex() const
282 //mask out the type information set for value types
283 return property & 0xFF00FFFF;
286 QObject *QV4Bindings::Binding::object() const
291 void QV4Bindings::Subscription::subscriptionCallback(QQmlNotifierEndpoint *e, void **)
293 Subscription *s = static_cast<Subscription *>(e);
294 s->bindings->subscriptionNotify(s->method);
297 void QV4Bindings::subscriptionNotify(int id)
299 QV4Program::BindingReferenceList *list = program->signalTable(id);
301 for (quint32 ii = 0; ii < list->count; ++ii) {
302 QV4Program::BindingReference *bindingRef = list->bindings + ii;
304 Binding *binding = bindings + bindingRef->binding;
306 if (binding->executedBlocks & bindingRef->blockMask) {
307 run(binding, QQmlPropertyPrivate::DontRemoveBinding);
312 void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags)
314 if (!binding->enabled)
317 QQmlContextData *context = QQmlAbstractExpression::context();
318 if (!context || !context->isValid())
321 QQmlTrace trace("V4 Binding Update");
322 trace.addDetail("URL", context->url);
323 trace.addDetail("Line", binding->line);
324 trace.addDetail("Column", binding->column);
326 QQmlBindingProfiler prof(context->urlString, binding->line, binding->column);
328 if (binding->updating) {
330 if (binding->property & 0xFFFF0000) {
331 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
333 QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
336 name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
337 name.append(QLatin1String("."));
338 name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
340 name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
342 qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name);
346 binding->updating = true;
347 if (binding->property & 0xFFFF0000) {
348 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
350 QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
352 vt->read(binding->target, binding->property & 0xFFFF);
354 QObject *target = vt;
355 run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags);
357 vt->write(binding->target, binding->property & 0xFFFF, flags);
359 run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags);
361 binding->updating = false;
365 void QV4Bindings::unsubscribe(int subIndex)
367 Subscription *sub = (subscriptions + subIndex);
371 void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex)
373 unsubscribe(subIndex);
375 if (p->idValues[idIndex]) {
376 Subscription *sub = (subscriptions + subIndex);
377 sub->bindings = this;
378 sub->method = subIndex;
379 sub->connect(&p->idValues[idIndex].bindings);
383 void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
385 Subscription *sub = (subscriptions + subIndex);
386 if (sub->isConnected(o, notifyIndex))
388 sub->bindings = this;
389 sub->method = subIndex;
391 sub->connect(o, notifyIndex);
396 static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
398 QVariant qtscript = qtscriptRaw;
400 if (qtscript.userType() == v4.userType()) {
401 } else if (qtscript.canConvert((QVariant::Type)v4.userType())) {
402 qtscript.convert((QVariant::Type)v4.userType());
403 } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) {
404 qtscript = qVariantFromValue<QObject *>(0);
409 int type = qtscript.userType();
411 if (type == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
412 return QQmlMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData());
413 } else if (type == QMetaType::Double) {
415 double la = qvariant_cast<double>(qtscript);
416 double lr = qvariant_cast<double>(v4);
418 return la == lr || (qIsNaN(la) && qIsNaN(lr));
420 } else if (type == QMetaType::Float) {
422 float la = qvariant_cast<float>(qtscript);
423 float lr = qvariant_cast<float>(v4);
425 return la == lr || (qIsNaN(la) && qIsNaN(lr));
428 return qtscript == v4;
432 QByteArray testResultToString(const QVariant &result, bool undefined)
444 static void testBindingResult(const QString &binding, int line, int column,
445 QQmlContextData *context, QObject *scope,
446 const Register &result, int resultType)
448 QQmlExpression expression(context->asQQmlContext(), scope, binding);
449 bool isUndefined = false;
450 QVariant value = expression.evaluate(&isUndefined);
452 bool iserror = false;
453 QByteArray qtscriptResult;
456 if (expression.hasError()) {
458 qtscriptResult = "exception";
459 } else if ((value.userType() != resultType) && (resultType != QMetaType::QVariant)) {
460 // Override the QMetaType conversions to make them more JS friendly.
461 if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
462 resultType == QMetaType::QUrl)) {
463 // number to string-like conversion.
464 value = QVariant::fromValue<QString>(QString::number(value.toDouble(), 'g', 16));
465 } else if (value.userType() == QMetaType::QUrl && resultType == QMetaType::Bool) {
466 // url to bool conversion
467 value = QVariant::fromValue<bool>(!value.toUrl().isEmpty());
470 if (!value.isNull() && !value.convert(resultType)) {
472 qtscriptResult = "exception";
473 } else if (resultType == QMetaType::QUrl) {
474 // a V8 value was converted to QUrl.
475 value = QVariant::fromValue<QUrl>(context->resolvedUrl(value.toUrl()));
480 qtscriptResult = testResultToString(value, isUndefined);
482 if (isUndefined && result.isUndefined()) {
484 } else if(isUndefined != result.isUndefined()) {
489 if (!result.isUndefined()) {
490 switch (resultType) {
491 case QMetaType::QString:
492 v4value = *result.getstringptr();
494 case QMetaType::QUrl:
495 v4value = *result.geturlptr();
497 case QMetaType::QObjectStar:
498 v4value = qVariantFromValue<QObject *>(result.getQObject());
500 case QMetaType::Bool:
501 v4value = result.getbool();
504 v4value = result.getint();
506 case QMetaType::Double:
507 v4value = result.getnumber();
509 case QMetaType::QColor:
510 v4value = QVariant(QMetaType::QColor, result.typeDataPtr());
512 case QMetaType::QVariant:
513 v4value = *result.getvariantptr();
516 if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
517 v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
520 v4Result = "Unknown V4 type";
524 if (v4Result.isEmpty())
525 v4Result = testResultToString(v4value, result.isUndefined());
527 if (!testCompareVariants(value, v4value))
531 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
533 qWarning().nospace() << " Binding: " << binding;
534 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
535 qWarning().nospace() << " V4: " << v4Result.constData();
539 static void testBindingException(const QString &binding, int line, int column,
540 QQmlContextData *context, QObject *scope)
542 QQmlExpression expression(context->asQQmlContext(), scope, binding);
543 bool isUndefined = false;
544 QVariant value = expression.evaluate(&isUndefined);
546 if (!expression.hasError()) {
547 QByteArray qtscriptResult = testResultToString(value, isUndefined);
548 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
549 qWarning().nospace() << " Binding: " << binding;
550 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
551 qWarning().nospace() << " V4: exception";
555 static void throwException(int id, QQmlDelayedError *error,
556 QV4Program *program, QQmlContextData *context,
557 const QString &description = QString())
559 error->error.setUrl(context->url);
560 if (description.isEmpty())
561 error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
563 error->error.setDescription(description);
565 quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id);
566 error->error.setLine((e >> 32) & 0xFFFFFFFF);
567 error->error.setColumn(e & 0xFFFFFFFF);
569 error->error.setLine(-1);
570 error->error.setColumn(-1);
572 if (!context->engine || !error->addError(QQmlEnginePrivate::get(context->engine)))
573 QQmlEnginePrivate::warning(context->engine, error->error);
576 const double QV4Bindings::D32 = 4294967296.0;
578 qint32 QV4Bindings::toInt32(double n)
580 if (qIsNaN(n) || qIsInf(n) || (n == 0))
583 double sign = (n < 0) ? -1.0 : 1.0;
584 double abs_n = fabs(n);
586 n = ::fmod(sign * ::floor(abs_n), D32);
587 const double D31 = D32 / 2.0;
589 if (sign == -1 && n < -D31)
592 else if (sign != -1 && n >= D31)
598 inline quint32 QV4Bindings::toUint32(double n)
600 if (qIsNaN(n) || qIsInf(n) || (n == 0))
603 double sign = (n < 0) ? -1.0 : 1.0;
604 double abs_n = fabs(n);
606 n = ::fmod(sign * ::floor(abs_n), D32);
614 #define THROW_EXCEPTION_STR(id, str) { \
615 if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \
616 throwException((id), error, program, context, (str)); \
617 goto exceptionExit; \
620 #define THROW_VALUE_EXCEPTION_STR(id, str) { \
621 throwException((id), error, program, context, (str)); \
622 goto exceptionExit; \
625 #define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
627 #define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
628 #define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg))
630 #define STRING_REGISTER(reg) { \
631 registers[(reg)].settype(QStringType); \
632 MARK_REGISTER(reg); \
635 #define URL_REGISTER(reg) { \
636 registers[(reg)].settype(QUrlType); \
637 MARK_REGISTER(reg); \
640 #define COLOR_REGISTER(reg) { \
641 registers[(reg)].settype(QColorType); \
642 MARK_REGISTER(reg); \
645 #define VARIANT_REGISTER(reg) { \
646 registers[(reg)].settype(QVariantType); \
647 MARK_REGISTER(reg); \
650 #ifdef QML_THREADED_INTERPRETER
651 void **QV4Bindings::getDecodeInstrTable()
653 static void **decode_instr;
655 QV4Bindings *dummy = new QV4Bindings(0, 0, 0);
656 quint32 executedBlocks = 0;
657 dummy->run(0, executedBlocks, 0, 0, 0, 0,
658 QQmlPropertyPrivate::BypassInterceptor,
666 void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
667 QQmlContextData *context, QQmlDelayedError *error,
668 QObject *scope, QObject *output,
669 QQmlPropertyPrivate::WriteFlags storeFlags
670 #ifdef QML_THREADED_INTERPRETER
675 #ifdef QML_THREADED_INTERPRETER
677 static void *decode_instr[] = {
678 FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR)
681 *table = decode_instr;
687 error->removeError();
689 Register registers[32];
690 quint32 cleanupRegisterMask = 0;
694 const char *code = program->instructions();
695 code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
696 const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
698 const char *data = program->data();
700 QString *testBindingSource = 0;
701 bool testBinding = false;
703 int bindingColumn = 0;
705 #ifdef QML_THREADED_INTERPRETER
706 goto *instr->common.code;
709 switch (instr->common.type) {
712 QML_V4_BEGIN_INSTR(Noop, common)
713 QML_V4_END_INSTR(Noop, common)
715 QML_V4_BEGIN_INSTR(BindingId, id)
716 bindingLine = instr->id.line;
717 bindingColumn = instr->id.column;
718 QML_V4_END_INSTR(BindingId, id)
720 QML_V4_BEGIN_INSTR(SubscribeId, subscribeop)
721 subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset);
722 QML_V4_END_INSTR(SubscribeId, subscribeop)
724 QML_V4_BEGIN_INSTR(Subscribe, subscribeop)
727 const Register &object = registers[instr->subscribeop.reg];
728 if (!object.isUndefined()) o = object.getQObject();
729 subscribe(o, instr->subscribeop.index, instr->subscribeop.offset);
731 QML_V4_END_INSTR(Subscribe, subscribeop)
733 QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe)
735 Register ® = registers[instr->fetchAndSubscribe.reg];
737 if (reg.isUndefined())
738 THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
740 QObject *object = reg.getQObject();
744 int subIdx = instr->fetchAndSubscribe.subscription;
745 Subscription *sub = 0;
747 sub = (subscriptions + subIdx);
748 sub->bindings = this;
749 sub->method = subIdx;
752 const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType;
754 if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
755 MARK_REGISTER(instr->fetchAndSubscribe.reg);
756 QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
757 accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
760 if (valueType == FloatType) {
762 const double v = reg.getfloat();
766 if (accessors->notifier) {
767 QQmlNotifier *notifier = 0;
768 accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier);
769 if (notifier) sub->connect(notifier);
770 } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
771 sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex);
775 QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
777 QML_V4_BEGIN_INSTR(LoadId, load)
778 registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
779 QML_V4_END_INSTR(LoadId, load)
781 QML_V4_BEGIN_INSTR(LoadScope, load)
782 registers[instr->load.reg].setQObject(scope);
783 QML_V4_END_INSTR(LoadScope, load)
785 QML_V4_BEGIN_INSTR(LoadRoot, load)
786 registers[instr->load.reg].setQObject(context->contextObject);
787 QML_V4_END_INSTR(LoadRoot, load)
789 QML_V4_BEGIN_INSTR(LoadModuleObject, load)
791 Register ® = registers[instr->load.reg];
793 const QString *name = reg.getstringptr();
794 QQmlTypeNameCache::Result r = context->imports->query(*name);
797 if (r.isValid() && r.importNamespace) {
798 QQmlMetaType::ModuleApiInstance *moduleApi = context->imports->moduleApi(r.importNamespace);
800 if (moduleApi->qobjectCallback) {
801 moduleApi->qobjectApi = moduleApi->qobjectCallback(context->engine, context->engine);
802 moduleApi->qobjectCallback = 0;
803 moduleApi->scriptCallback = 0;
805 if (moduleApi->qobjectApi)
806 reg.setQObject(moduleApi->qobjectApi);
810 QML_V4_END_INSTR(LoadModuleObject, load)
812 QML_V4_BEGIN_INSTR(LoadAttached, attached)
814 const Register &input = registers[instr->attached.reg];
815 Register &output = registers[instr->attached.output];
816 if (input.isUndefined())
817 THROW_EXCEPTION(instr->attached.exceptionId);
819 QObject *object = registers[instr->attached.reg].getQObject();
821 output.setUndefined();
823 QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true);
825 output.setQObject(attached);
828 QML_V4_END_INSTR(LoadAttached, attached)
830 QML_V4_BEGIN_INSTR(UnaryNot, unaryop)
832 registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool());
834 QML_V4_END_INSTR(UnaryNot, unaryop)
836 QML_V4_BEGIN_INSTR(UnaryMinusNumber, unaryop)
838 registers[instr->unaryop.output].setnumber(-registers[instr->unaryop.src].getnumber());
840 QML_V4_END_INSTR(UnaryMinusNumber, unaryop)
842 QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
844 registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint());
846 QML_V4_END_INSTR(UnaryMinusInt, unaryop)
848 QML_V4_BEGIN_INSTR(UnaryPlusNumber, unaryop)
850 registers[instr->unaryop.output].setnumber(+registers[instr->unaryop.src].getnumber());
852 QML_V4_END_INSTR(UnaryPlusNumber, unaryop)
854 QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
856 registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint());
858 QML_V4_END_INSTR(UnaryPlusInt, unaryop)
860 QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop)
862 const Register &src = registers[instr->unaryop.src];
863 Register &output = registers[instr->unaryop.output];
864 if (src.isUndefined()) output.setUndefined();
865 else output.setint(src.getbool());
867 QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
869 QML_V4_BEGIN_INSTR(ConvertBoolToNumber, unaryop)
871 const Register &src = registers[instr->unaryop.src];
872 Register &output = registers[instr->unaryop.output];
873 if (src.isUndefined()) output.setUndefined();
874 else output.setnumber(src.getbool());
876 QML_V4_END_INSTR(ConvertBoolToNumber, unaryop)
878 QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
880 const Register &src = registers[instr->unaryop.src];
881 Register &output = registers[instr->unaryop.output];
882 if (src.isUndefined()) {
883 output.setUndefined();
885 new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false"));
886 STRING_REGISTER(instr->unaryop.output);
889 QML_V4_END_INSTR(ConvertBoolToString, unaryop)
891 QML_V4_BEGIN_INSTR(ConvertBoolToVariant, unaryop)
893 const Register &src = registers[instr->unaryop.src];
894 Register &output = registers[instr->unaryop.output];
895 if (src.isUndefined()) {
896 output.setUndefined();
898 new (output.getvariantptr()) QVariant(src.getbool());
899 VARIANT_REGISTER(instr->unaryop.output);
902 QML_V4_END_INSTR(ConvertBoolToVariant, unaryop)
904 QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
906 const Register &src = registers[instr->unaryop.src];
907 Register &output = registers[instr->unaryop.output];
908 if (src.isUndefined()) output.setUndefined();
909 else output.setbool(src.getint());
911 QML_V4_END_INSTR(ConvertIntToBool, unaryop)
913 QML_V4_BEGIN_INSTR(ConvertIntToNumber, unaryop)
915 const Register &src = registers[instr->unaryop.src];
916 Register &output = registers[instr->unaryop.output];
917 if (src.isUndefined()) output.setUndefined();
918 else output.setnumber(double(src.getint()));
920 QML_V4_END_INSTR(ConvertIntToNumber, unaryop)
922 QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
924 const Register &src = registers[instr->unaryop.src];
925 Register &output = registers[instr->unaryop.output];
926 if (src.isUndefined()) {
927 output.setUndefined();
929 new (output.getstringptr()) QString(QString::number(src.getint()));
930 STRING_REGISTER(instr->unaryop.output);
933 QML_V4_END_INSTR(ConvertIntToString, unaryop)
935 QML_V4_BEGIN_INSTR(ConvertIntToVariant, unaryop)
937 const Register &src = registers[instr->unaryop.src];
938 Register &output = registers[instr->unaryop.output];
939 if (src.isUndefined()) {
940 output.setUndefined();
942 new (output.getvariantptr()) QVariant(src.getint());
943 VARIANT_REGISTER(instr->unaryop.output);
946 QML_V4_END_INSTR(ConvertIntToVariant, unaryop)
948 QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
950 const Register &src = registers[instr->unaryop.src];
951 Register &output = registers[instr->unaryop.output];
952 if (src.isUndefined()) output.setUndefined();
953 else output.setbool(src.getnumber() != 0);
955 QML_V4_END_INSTR(ConvertNumberToBool, unaryop)
957 QML_V4_BEGIN_INSTR(ConvertNumberToInt, unaryop)
959 const Register &src = registers[instr->unaryop.src];
960 Register &output = registers[instr->unaryop.output];
961 if (src.isUndefined()) output.setUndefined();
962 else output.setint(toInt32(src.getnumber()));
964 QML_V4_END_INSTR(ConvertNumberToInt, unaryop)
966 QML_V4_BEGIN_INSTR(ConvertNumberToString, unaryop)
968 const Register &src = registers[instr->unaryop.src];
969 Register &output = registers[instr->unaryop.output];
971 if (src.isUndefined()) {
972 output.setUndefined();
974 new (output.getstringptr()) QString(QString::number(src.getnumber(), 'g', 16));
975 STRING_REGISTER(instr->unaryop.output);
978 QML_V4_END_INSTR(ConvertNumberToString, unaryop)
980 QML_V4_BEGIN_INSTR(ConvertNumberToVariant, unaryop)
982 const Register &src = registers[instr->unaryop.src];
983 Register &output = registers[instr->unaryop.output];
984 if (src.isUndefined()) {
985 output.setUndefined();
987 new (output.getvariantptr()) QVariant(src.getnumber());
988 VARIANT_REGISTER(instr->unaryop.output);
991 QML_V4_END_INSTR(ConvertNumberToVariant, unaryop)
993 QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
995 const Register &src = registers[instr->unaryop.src];
996 Register &output = registers[instr->unaryop.output];
998 if (src.isUndefined()) {
999 output.setUndefined();
1001 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1002 // Ideally we should just call the methods in the QScript namespace directly.
1003 QJSValue tmp(*src.getstringptr());
1004 if (instr->unaryop.src == instr->unaryop.output) {
1005 output.cleanupString();
1006 MARK_CLEAN_REGISTER(instr->unaryop.output);
1008 output.setbool(tmp.toBool());
1011 QML_V4_END_INSTR(ConvertStringToBool, unaryop)
1013 QML_V4_BEGIN_INSTR(ConvertStringToInt, 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 QJSValue tmp(*src.getstringptr());
1024 if (instr->unaryop.src == instr->unaryop.output) {
1025 output.cleanupString();
1026 MARK_CLEAN_REGISTER(instr->unaryop.output);
1028 output.setint(tmp.toInt());
1031 QML_V4_END_INSTR(ConvertStringToInt, unaryop)
1033 QML_V4_BEGIN_INSTR(ConvertStringToNumber, 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 QJSValue tmp(*src.getstringptr());
1044 if (instr->unaryop.src == instr->unaryop.output) {
1045 output.cleanupString();
1046 MARK_CLEAN_REGISTER(instr->unaryop.output);
1048 output.setnumber(tmp.toNumber());
1051 QML_V4_END_INSTR(ConvertStringToNumber, unaryop)
1053 QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
1055 const Register &src = registers[instr->unaryop.src];
1056 Register &output = registers[instr->unaryop.output];
1058 if (src.isUndefined()) {
1059 output.setUndefined();
1061 const QString tmp(*src.getstringptr());
1062 if (instr->unaryop.src == instr->unaryop.output) {
1063 output.cleanupString();
1064 MARK_CLEAN_REGISTER(instr->unaryop.output);
1066 new (output.geturlptr()) QUrl(tmp);
1068 URL_REGISTER(instr->unaryop.output);
1071 QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
1073 QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop)
1075 const Register &src = registers[instr->unaryop.src];
1076 Register &output = registers[instr->unaryop.output];
1078 if (src.isUndefined()) {
1079 output.setUndefined();
1081 const QString tmp(*src.getstringptr());
1082 if (instr->unaryop.src == instr->unaryop.output) {
1083 output.cleanupString();
1084 MARK_CLEAN_REGISTER(instr->unaryop.output);
1086 QQml_valueTypeProvider()->createValueFromString(QMetaType::QColor, tmp, output.typeDataPtr(), output.dataSize());
1088 COLOR_REGISTER(instr->unaryop.output);
1091 QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
1093 QML_V4_BEGIN_INSTR(ConvertStringToVariant, unaryop)
1095 const Register &src = registers[instr->unaryop.src];
1096 Register &output = registers[instr->unaryop.output];
1097 if (src.isUndefined()) {
1098 output.setUndefined();
1100 const QString tmp(*src.getstringptr());
1101 if (instr->unaryop.src == instr->unaryop.output) {
1102 output.cleanupString();
1103 MARK_CLEAN_REGISTER(instr->unaryop.output);
1105 new (output.getvariantptr()) QVariant(tmp);
1107 VARIANT_REGISTER(instr->unaryop.output);
1110 QML_V4_END_INSTR(ConvertStringToVariant, unaryop)
1112 QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
1114 const Register &src = registers[instr->unaryop.src];
1115 Register &output = registers[instr->unaryop.output];
1117 if (src.isUndefined()) {
1118 output.setUndefined();
1120 const QUrl tmp(*src.geturlptr());
1121 if (instr->unaryop.src == instr->unaryop.output) {
1122 output.cleanupUrl();
1123 MARK_CLEAN_REGISTER(instr->unaryop.output);
1125 output.setbool(!tmp.isEmpty());
1128 QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
1130 QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
1132 const Register &src = registers[instr->unaryop.src];
1133 Register &output = registers[instr->unaryop.output];
1135 if (src.isUndefined()) {
1136 output.setUndefined();
1138 const QUrl tmp(*src.geturlptr());
1139 if (instr->unaryop.src == instr->unaryop.output) {
1140 output.cleanupUrl();
1141 MARK_CLEAN_REGISTER(instr->unaryop.output);
1143 new (output.getstringptr()) QString(tmp.toString());
1144 STRING_REGISTER(instr->unaryop.output);
1147 QML_V4_END_INSTR(ConvertUrlToString, unaryop)
1149 QML_V4_BEGIN_INSTR(ConvertUrlToVariant, unaryop)
1151 const Register &src = registers[instr->unaryop.src];
1152 Register &output = registers[instr->unaryop.output];
1154 if (src.isUndefined()) {
1155 output.setUndefined();
1157 const QUrl tmp(*src.geturlptr());
1158 if (instr->unaryop.src == instr->unaryop.output) {
1159 output.cleanupUrl();
1160 MARK_CLEAN_REGISTER(instr->unaryop.output);
1162 new (output.getvariantptr()) QVariant(tmp);
1163 VARIANT_REGISTER(instr->unaryop.output);
1166 QML_V4_END_INSTR(ConvertUrlToVariant, unaryop)
1168 QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
1170 const Register &src = registers[instr->unaryop.src];
1171 Register &output = registers[instr->unaryop.output];
1173 if (src.isUndefined()) {
1174 output.setUndefined();
1176 // for compatibility with color behavior in v8, always true
1177 output.setbool(true);
1180 QML_V4_END_INSTR(ConvertColorToBool, unaryop)
1182 QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop)
1184 const Register &src = registers[instr->unaryop.src];
1185 Register &output = registers[instr->unaryop.output];
1187 if (src.isUndefined()) {
1188 output.setUndefined();
1190 QQml_valueTypeProvider()->createStringFromValue(QMetaType::QColor, src.typeDataPtr(), output.getstringptr());
1191 STRING_REGISTER(instr->unaryop.output);
1194 QML_V4_END_INSTR(ConvertColorToString, unaryop)
1196 QML_V4_BEGIN_INSTR(ConvertColorToVariant, unaryop)
1198 const Register &src = registers[instr->unaryop.src];
1199 Register &output = registers[instr->unaryop.output];
1201 if (src.isUndefined()) {
1202 output.setUndefined();
1204 QVariant tmp(QMetaType::QColor, src.typeDataPtr());
1205 if (instr->unaryop.src == instr->unaryop.output) {
1206 output.cleanupColor();
1207 MARK_CLEAN_REGISTER(instr->unaryop.output);
1209 new (output.getvariantptr()) QVariant(tmp);
1210 VARIANT_REGISTER(instr->unaryop.output);
1213 QML_V4_END_INSTR(ConvertColorToVariant, unaryop)
1215 QML_V4_BEGIN_INSTR(ConvertObjectToBool, unaryop)
1217 const Register &src = registers[instr->unaryop.src];
1218 Register &output = registers[instr->unaryop.output];
1220 if (src.isUndefined())
1221 output.setUndefined();
1223 output.setbool(src.getQObject() != 0);
1225 QML_V4_END_INSTR(ConvertObjectToBool, unaryop)
1227 QML_V4_BEGIN_INSTR(ConvertObjectToVariant, unaryop)
1229 const Register &src = registers[instr->unaryop.src];
1230 Register &output = registers[instr->unaryop.output];
1232 if (src.isUndefined())
1233 output.setUndefined();
1235 new (output.getvariantptr()) QVariant(qVariantFromValue<QObject *>(src.getQObject()));
1236 VARIANT_REGISTER(instr->unaryop.output);
1239 QML_V4_END_INSTR(ConvertObjectToVariant, unaryop)
1241 QML_V4_BEGIN_INSTR(ConvertNullToObject, unaryop)
1243 Register &output = registers[instr->unaryop.output];
1244 output.setQObject(0);
1246 QML_V4_END_INSTR(ConvertNullToObject, unaryop)
1248 QML_V4_BEGIN_INSTR(ConvertNullToVariant, unaryop)
1250 Register &output = registers[instr->unaryop.output];
1251 new (output.getvariantptr()) QVariant();
1252 VARIANT_REGISTER(instr->unaryop.output);
1254 QML_V4_END_INSTR(ConvertNullToVariant, unaryop)
1256 QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
1258 const Register &src = registers[instr->unaryop.src];
1259 Register &output = registers[instr->unaryop.output];
1260 if (src.isUndefined()) {
1261 output.setUndefined();
1263 const QUrl tmp(*src.geturlptr());
1264 if (instr->unaryop.src == instr->unaryop.output) {
1265 *output.geturlptr() = context->resolvedUrl(tmp);
1267 new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
1268 URL_REGISTER(instr->unaryop.output);
1272 QML_V4_END_INSTR(ResolveUrl, unaryop)
1274 QML_V4_BEGIN_INSTR(MathSinNumber, unaryop)
1276 const Register &src = registers[instr->unaryop.src];
1277 Register &output = registers[instr->unaryop.output];
1278 if (src.isUndefined()) output.setUndefined();
1279 else output.setnumber(qSin(src.getnumber()));
1281 QML_V4_END_INSTR(MathSinNumber, unaryop)
1283 QML_V4_BEGIN_INSTR(MathCosNumber, unaryop)
1285 const Register &src = registers[instr->unaryop.src];
1286 Register &output = registers[instr->unaryop.output];
1287 if (src.isUndefined()) output.setUndefined();
1288 else output.setnumber(qCos(src.getnumber()));
1290 QML_V4_END_INSTR(MathCosNumber, unaryop)
1292 QML_V4_BEGIN_INSTR(MathAbsNumber, unaryop)
1294 const Register &src = registers[instr->unaryop.src];
1295 Register &output = registers[instr->unaryop.output];
1296 if (src.isUndefined()) output.setUndefined();
1297 else output.setnumber(qAbs(src.getnumber()));
1299 QML_V4_END_INSTR(MathAbsNumber, unaryop)
1301 QML_V4_BEGIN_INSTR(MathRoundNumber, unaryop)
1303 const Register &src = registers[instr->unaryop.src];
1304 Register &output = registers[instr->unaryop.output];
1305 if (src.isUndefined()) output.setUndefined();
1306 else output.setint(qRound(src.getnumber()));
1308 QML_V4_END_INSTR(MathRoundNumber, unaryop)
1310 QML_V4_BEGIN_INSTR(MathFloorNumber, unaryop)
1312 const Register &src = registers[instr->unaryop.src];
1313 Register &output = registers[instr->unaryop.output];
1314 if (src.isUndefined()) output.setUndefined();
1315 else output.setint(qFloor(src.getnumber()));
1317 QML_V4_END_INSTR(MathFloorNumber, unaryop)
1319 QML_V4_BEGIN_INSTR(MathCeilNumber, unaryop)
1321 const Register &src = registers[instr->unaryop.src];
1322 Register &output = registers[instr->unaryop.output];
1323 if (src.isUndefined()) output.setUndefined();
1324 else output.setint(qCeil(src.getnumber()));
1326 QML_V4_END_INSTR(MathCeilNumber, unaryop)
1328 QML_V4_BEGIN_INSTR(MathPINumber, unaryop)
1330 static const double qmlPI = 2.0 * qAsin(1.0);
1331 Register &output = registers[instr->unaryop.output];
1332 output.setnumber(qmlPI);
1334 QML_V4_END_INSTR(MathPINumber, unaryop)
1336 QML_V4_BEGIN_INSTR(LoadNull, null_value)
1337 registers[instr->null_value.reg].setNull();
1338 QML_V4_END_INSTR(LoadNull, null_value)
1340 QML_V4_BEGIN_INSTR(LoadNumber, number_value)
1341 registers[instr->number_value.reg].setnumber(instr->number_value.value);
1342 QML_V4_END_INSTR(LoadNumber, number_value)
1344 QML_V4_BEGIN_INSTR(LoadInt, int_value)
1345 registers[instr->int_value.reg].setint(instr->int_value.value);
1346 QML_V4_END_INSTR(LoadInt, int_value)
1348 QML_V4_BEGIN_INSTR(LoadBool, bool_value)
1349 registers[instr->bool_value.reg].setbool(instr->bool_value.value);
1350 QML_V4_END_INSTR(LoadBool, bool_value)
1352 QML_V4_BEGIN_INSTR(LoadString, string_value)
1354 Register &output = registers[instr->string_value.reg];
1355 QChar *string = (QChar *)(data + instr->string_value.offset);
1356 new (output.getstringptr()) QString(string, instr->string_value.length);
1357 STRING_REGISTER(instr->string_value.reg);
1359 QML_V4_END_INSTR(LoadString, string_value)
1361 QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
1363 testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
1366 QML_V4_END_INSTR(String, string_value)
1368 QML_V4_BEGIN_INSTR(BitAndInt, binaryop)
1370 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() &
1371 registers[instr->binaryop.right].getint());
1373 QML_V4_END_INSTR(BitAndInt, binaryop)
1375 QML_V4_BEGIN_INSTR(BitOrInt, binaryop)
1377 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() |
1378 registers[instr->binaryop.right].getint());
1380 QML_V4_END_INSTR(BitAndInt, binaryop)
1382 QML_V4_BEGIN_INSTR(BitXorInt, binaryop)
1384 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^
1385 registers[instr->binaryop.right].getint());
1387 QML_V4_END_INSTR(BitXorInt, binaryop)
1389 QML_V4_BEGIN_INSTR(AddNumber, binaryop)
1391 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() +
1392 registers[instr->binaryop.right].getnumber());
1394 QML_V4_END_INSTR(AddNumber, binaryop)
1396 QML_V4_BEGIN_INSTR(AddString, binaryop)
1398 QString &string = *registers[instr->binaryop.output].getstringptr();
1399 if (instr->binaryop.output == instr->binaryop.left) {
1400 string += registers[instr->binaryop.right].getstringptr();
1402 string = *registers[instr->binaryop.left].getstringptr() +
1403 *registers[instr->binaryop.right].getstringptr();
1406 QML_V4_END_INSTR(AddString, binaryop)
1408 QML_V4_BEGIN_INSTR(SubNumber, binaryop)
1410 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() -
1411 registers[instr->binaryop.right].getnumber());
1413 QML_V4_END_INSTR(SubNumber, binaryop)
1415 QML_V4_BEGIN_INSTR(MulNumber, binaryop)
1417 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() *
1418 registers[instr->binaryop.right].getnumber());
1420 QML_V4_END_INSTR(MulNumber, binaryop)
1422 QML_V4_BEGIN_INSTR(DivNumber, binaryop)
1424 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() /
1425 registers[instr->binaryop.right].getnumber());
1427 QML_V4_END_INSTR(DivNumber, binaryop)
1429 QML_V4_BEGIN_INSTR(ModNumber, binaryop)
1431 Register &target = registers[instr->binaryop.output];
1432 const Register &left = registers[instr->binaryop.left];
1433 const Register &right = registers[instr->binaryop.right];
1434 target.setnumber(::fmod(left.getnumber(), right.getnumber()));
1436 QML_V4_END_INSTR(ModInt, binaryop)
1438 QML_V4_BEGIN_INSTR(LShiftInt, binaryop)
1440 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() <<
1441 registers[instr->binaryop.right].getint());
1443 QML_V4_END_INSTR(LShiftInt, binaryop)
1445 QML_V4_BEGIN_INSTR(RShiftInt, binaryop)
1447 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >>
1448 registers[instr->binaryop.right].getint());
1450 QML_V4_END_INSTR(RShiftInt, binaryop)
1452 QML_V4_BEGIN_INSTR(URShiftInt, binaryop)
1454 registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >>
1455 registers[instr->binaryop.right].getint());
1457 QML_V4_END_INSTR(URShiftInt, binaryop)
1459 QML_V4_BEGIN_INSTR(GtNumber, binaryop)
1461 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >
1462 registers[instr->binaryop.right].getnumber());
1464 QML_V4_END_INSTR(GtNumber, binaryop)
1466 QML_V4_BEGIN_INSTR(LtNumber, binaryop)
1468 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <
1469 registers[instr->binaryop.right].getnumber());
1471 QML_V4_END_INSTR(LtNumber, binaryop)
1473 QML_V4_BEGIN_INSTR(GeNumber, binaryop)
1475 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >=
1476 registers[instr->binaryop.right].getnumber());
1478 QML_V4_END_INSTR(GeNumber, binaryop)
1480 QML_V4_BEGIN_INSTR(LeNumber, binaryop)
1482 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <=
1483 registers[instr->binaryop.right].getnumber());
1485 QML_V4_END_INSTR(LeNumber, binaryop)
1487 QML_V4_BEGIN_INSTR(EqualNumber, binaryop)
1489 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
1490 registers[instr->binaryop.right].getnumber());
1492 QML_V4_END_INSTR(EqualNumber, binaryop)
1494 QML_V4_BEGIN_INSTR(NotEqualNumber, binaryop)
1496 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
1497 registers[instr->binaryop.right].getnumber());
1499 QML_V4_END_INSTR(NotEqualNumber, binaryop)
1501 QML_V4_BEGIN_INSTR(StrictEqualNumber, binaryop)
1503 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
1504 registers[instr->binaryop.right].getnumber());
1506 QML_V4_END_INSTR(StrictEqualNumber, binaryop)
1508 QML_V4_BEGIN_INSTR(StrictNotEqualNumber, binaryop)
1510 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
1511 registers[instr->binaryop.right].getnumber());
1513 QML_V4_END_INSTR(StrictNotEqualNumber, binaryop)
1515 QML_V4_BEGIN_INSTR(GtString, binaryop)
1517 const QString &a = *registers[instr->binaryop.left].getstringptr();
1518 const QString &b = *registers[instr->binaryop.right].getstringptr();
1519 bool result = a > b;
1520 if (instr->binaryop.left == instr->binaryop.output) {
1521 registers[instr->binaryop.output].cleanupString();
1522 MARK_CLEAN_REGISTER(instr->binaryop.output);
1524 registers[instr->binaryop.output].setbool(result);
1526 QML_V4_END_INSTR(GtString, binaryop)
1528 QML_V4_BEGIN_INSTR(LtString, binaryop)
1530 const QString &a = *registers[instr->binaryop.left].getstringptr();
1531 const QString &b = *registers[instr->binaryop.right].getstringptr();
1532 bool result = a < b;
1533 if (instr->binaryop.left == instr->binaryop.output) {
1534 registers[instr->binaryop.output].cleanupString();
1535 MARK_CLEAN_REGISTER(instr->binaryop.output);
1537 registers[instr->binaryop.output].setbool(result);
1539 QML_V4_END_INSTR(LtString, binaryop)
1541 QML_V4_BEGIN_INSTR(GeString, binaryop)
1543 const QString &a = *registers[instr->binaryop.left].getstringptr();
1544 const QString &b = *registers[instr->binaryop.right].getstringptr();
1545 bool result = a >= b;
1546 if (instr->binaryop.left == instr->binaryop.output) {
1547 registers[instr->binaryop.output].cleanupString();
1548 MARK_CLEAN_REGISTER(instr->binaryop.output);
1550 registers[instr->binaryop.output].setbool(result);
1552 QML_V4_END_INSTR(GeString, binaryop)
1554 QML_V4_BEGIN_INSTR(LeString, binaryop)
1556 const QString &a = *registers[instr->binaryop.left].getstringptr();
1557 const QString &b = *registers[instr->binaryop.right].getstringptr();
1558 bool result = a <= b;
1559 if (instr->binaryop.left == instr->binaryop.output) {
1560 registers[instr->binaryop.output].cleanupString();
1561 MARK_CLEAN_REGISTER(instr->binaryop.output);
1563 registers[instr->binaryop.output].setbool(result);
1565 QML_V4_END_INSTR(LeString, binaryop)
1567 QML_V4_BEGIN_INSTR(EqualString, binaryop)
1569 const QString &a = *registers[instr->binaryop.left].getstringptr();
1570 const QString &b = *registers[instr->binaryop.right].getstringptr();
1571 bool result = a == b;
1572 if (instr->binaryop.left == instr->binaryop.output) {
1573 registers[instr->binaryop.output].cleanupString();
1574 MARK_CLEAN_REGISTER(instr->binaryop.output);
1576 registers[instr->binaryop.output].setbool(result);
1578 QML_V4_END_INSTR(EqualString, binaryop)
1580 QML_V4_BEGIN_INSTR(NotEqualString, binaryop)
1582 const QString &a = *registers[instr->binaryop.left].getstringptr();
1583 const QString &b = *registers[instr->binaryop.right].getstringptr();
1584 bool result = a != b;
1585 if (instr->binaryop.left == instr->binaryop.output) {
1586 registers[instr->binaryop.output].cleanupString();
1587 MARK_CLEAN_REGISTER(instr->binaryop.output);
1589 registers[instr->binaryop.output].setbool(result);
1591 QML_V4_END_INSTR(NotEqualString, binaryop)
1593 QML_V4_BEGIN_INSTR(StrictEqualString, binaryop)
1595 const QString &a = *registers[instr->binaryop.left].getstringptr();
1596 const QString &b = *registers[instr->binaryop.right].getstringptr();
1597 bool result = a == b;
1598 if (instr->binaryop.left == instr->binaryop.output) {
1599 registers[instr->binaryop.output].cleanupString();
1600 MARK_CLEAN_REGISTER(instr->binaryop.output);
1602 registers[instr->binaryop.output].setbool(result);
1604 QML_V4_END_INSTR(StrictEqualString, binaryop)
1606 QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop)
1608 const QString &a = *registers[instr->binaryop.left].getstringptr();
1609 const QString &b = *registers[instr->binaryop.right].getstringptr();
1610 bool result = a != b;
1611 if (instr->binaryop.left == instr->binaryop.output) {
1612 registers[instr->binaryop.output].cleanupString();
1613 MARK_CLEAN_REGISTER(instr->binaryop.output);
1615 registers[instr->binaryop.output].setbool(result);
1617 QML_V4_END_INSTR(StrictNotEqualString, binaryop)
1619 QML_V4_BEGIN_INSTR(EqualObject, binaryop)
1621 const Register &left = registers[instr->binaryop.left];
1622 const Register &right = registers[instr->binaryop.right];
1623 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
1624 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
1625 registers[instr->binaryop.output].setbool(leftobj == rightobj);
1627 QML_V4_END_INSTR(EqualObject, binaryop)
1629 QML_V4_BEGIN_INSTR(NotEqualObject, binaryop)
1631 const Register &left = registers[instr->binaryop.left];
1632 const Register &right = registers[instr->binaryop.right];
1633 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
1634 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
1635 registers[instr->binaryop.output].setbool(leftobj != rightobj);
1637 QML_V4_END_INSTR(NotEqualObject, binaryop)
1639 QML_V4_BEGIN_INSTR(StrictEqualObject, binaryop)
1641 const Register &left = registers[instr->binaryop.left];
1642 const Register &right = registers[instr->binaryop.right];
1643 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
1644 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
1645 registers[instr->binaryop.output].setbool(leftobj == rightobj);
1647 QML_V4_END_INSTR(StrictEqualObject, binaryop)
1649 QML_V4_BEGIN_INSTR(StrictNotEqualObject, binaryop)
1651 const Register &left = registers[instr->binaryop.left];
1652 const Register &right = registers[instr->binaryop.right];
1653 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
1654 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
1655 registers[instr->binaryop.output].setbool(leftobj != rightobj);
1657 QML_V4_END_INSTR(StrictNotEqualObject, binaryop)
1659 QML_V4_BEGIN_INSTR(MathMaxNumber, binaryop)
1661 const Register &left = registers[instr->binaryop.left];
1662 const Register &right = registers[instr->binaryop.right];
1663 Register &output = registers[instr->binaryop.output];
1664 if (left.isUndefined() || right.isUndefined()) output.setUndefined();
1665 else output.setnumber(qMax(left.getnumber(), right.getnumber()));
1667 QML_V4_END_INSTR(MathMaxNumber, binaryop)
1669 QML_V4_BEGIN_INSTR(MathMinNumber, binaryop)
1671 const Register &left = registers[instr->binaryop.left];
1672 const Register &right = registers[instr->binaryop.right];
1673 Register &output = registers[instr->binaryop.output];
1674 if (left.isUndefined() || right.isUndefined()) output.setUndefined();
1675 else output.setnumber(qMin(left.getnumber(), right.getnumber()));
1677 QML_V4_END_INSTR(MathMinNumber, binaryop)
1679 QML_V4_BEGIN_INSTR(NewString, construct)
1681 Register &output = registers[instr->construct.reg];
1682 new (output.getstringptr()) QString;
1683 STRING_REGISTER(instr->construct.reg);
1685 QML_V4_END_INSTR(NewString, construct)
1687 QML_V4_BEGIN_INSTR(NewUrl, construct)
1689 Register &output = registers[instr->construct.reg];
1690 new (output.geturlptr()) QUrl;
1691 URL_REGISTER(instr->construct.reg);
1693 QML_V4_END_INSTR(NewUrl, construct)
1695 QML_V4_BEGIN_INSTR(Fetch, fetch)
1697 Register ® = registers[instr->fetch.reg];
1699 if (reg.isUndefined())
1700 THROW_EXCEPTION(instr->fetch.exceptionId);
1702 QObject *object = reg.getQObject();
1704 THROW_EXCEPTION(instr->fetch.exceptionId);
1706 const Register::Type valueType = (Register::Type)instr->fetch.valueType;
1707 reg.init(valueType);
1708 if (instr->fetch.valueType >= FirstCleanupType)
1709 MARK_REGISTER(instr->fetch.reg);
1710 void *argv[] = { reg.typeDataPtr(), 0 };
1711 QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
1712 if (valueType == FloatType) {
1714 const double v = reg.getfloat();
1719 QML_V4_END_INSTR(Fetch, fetch)
1721 QML_V4_BEGIN_INSTR(TestV4Store, storetest)
1723 Register &data = registers[instr->storetest.reg];
1724 testBindingResult(*testBindingSource, bindingLine, bindingColumn, context,
1725 scope, data, instr->storetest.regType);
1727 QML_V4_END_INSTR(TestV4Store, storetest)
1729 QML_V4_BEGIN_INSTR(Store, store)
1731 Register &data = registers[instr->store.reg];
1733 if (data.isUndefined())
1734 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
1736 if (data.gettype() == QObjectStarType) {
1737 if (QObject *dataObject = data.getQObject()) {
1738 const QMetaObject *dataMo = dataObject->metaObject();
1740 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
1741 QMetaProperty receiver = output->metaObject()->property(instr->store.index);
1742 const QMetaObject *receiverMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, receiver.userType());
1744 // Verify that these types are compatible
1745 if (!QQmlPropertyPrivate::canConvert(dataMo, receiverMo)) {
1746 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") +
1747 QLatin1String(dataMo->className()) +
1748 QLatin1String(" to ") +
1749 QLatin1String(receiverMo->className()));
1754 if (instr->store.valueType == FloatType) {
1755 // cast numbers to floats
1756 const float v = (float) data.getnumber();
1761 void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
1762 QMetaObject::metacall(output, QMetaObject::WriteProperty,
1763 instr->store.index, argv);
1767 QML_V4_END_INSTR(Store, store)
1769 QML_V4_BEGIN_INSTR(Copy, copy)
1770 registers[instr->copy.reg].copy(registers[instr->copy.src]);
1771 if (registers[instr->copy.reg].gettype() >= FirstCleanupType)
1772 MARK_REGISTER(instr->copy.reg);
1773 QML_V4_END_INSTR(Copy, copy)
1775 QML_V4_BEGIN_INSTR(Jump, jump)
1776 if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool())
1777 code += instr->jump.count;
1778 QML_V4_END_INSTR(Jump, jump)
1780 QML_V4_BEGIN_INSTR(BranchTrue, branchop)
1781 if (registers[instr->branchop.reg].getbool())
1782 code += instr->branchop.offset;
1783 QML_V4_END_INSTR(BranchTrue, branchop)
1785 QML_V4_BEGIN_INSTR(BranchFalse, branchop)
1786 if (! registers[instr->branchop.reg].getbool())
1787 code += instr->branchop.offset;
1788 QML_V4_END_INSTR(BranchFalse, branchop)
1790 QML_V4_BEGIN_INSTR(Branch, branchop)
1791 code += instr->branchop.offset;
1792 QML_V4_END_INSTR(Branch, branchop)
1794 QML_V4_BEGIN_INSTR(Block, blockop)
1795 executedBlocks |= instr->blockop.block;
1796 QML_V4_END_INSTR(Block, blockop)
1798 QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
1799 registers[instr->cleanup.reg].cleanup();
1800 QML_V4_END_INSTR(CleanupRegister, cleanup)
1802 QML_V4_BEGIN_INSTR(Throw, throwop)
1803 THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr());
1804 QML_V4_END_INSTR(Throw, throwop)
1806 #ifdef QML_THREADED_INTERPRETER
1810 qFatal("QV4: Unknown instruction %d encountered.", instr->common.type);
1817 Q_ASSERT(!"Unreachable code reached");
1821 delete testBindingSource;
1824 while (cleanupRegisterMask) {
1825 if (cleanupRegisterMask & 0x1)
1826 registers[reg].cleanup();
1829 cleanupRegisterMask >>= 1;