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>
51 #include <private/qv8_p.h>
52 #include <private/qjsconverter_p.h>
53 #include <private/qjsconverter_impl_p.h>
54 #include <private/qjsvalue_impl_p.h>
55 #include <private/qv8engine_impl_p.h>
57 #include <private/qqmlaccessors_p.h>
58 #include <private/qqmlprofilerservice_p.h>
59 #include <private/qqmlmetatype_p.h>
60 #include <private/qqmltrace_p.h>
61 #include <private/qqmlstringconverters_p.h>
62 #include <private/qqmlproperty_p.h>
63 #include <private/qqmlvmemetaobject_p.h>
65 #include <QtQml/qqmlinfo.h>
66 #include <QtCore/qnumeric.h>
67 #include <QtCore/qmath.h>
68 #include <math.h> // ::fmod
70 Q_DECLARE_METATYPE(QJSValue)
74 using namespace QQmlJS;
76 QQmlAbstractBinding::VTable QV4Bindings_Binding_vtable = {
77 QV4Bindings::Binding::destroy,
78 QQmlAbstractBinding::default_expression,
79 QV4Bindings::Binding::propertyIndex,
80 QV4Bindings::Binding::object,
81 QV4Bindings::Binding::setEnabled,
82 QV4Bindings::Binding::update,
83 QV4Bindings::Binding::retargetBinding
88 typedef QQmlRegisterType Type;
90 inline void setUndefined() { dataType = UndefinedType; }
91 inline void setNull() { dataType = NullType; }
92 inline void setNaN() { setnumber(qSNaN()); }
93 inline bool isUndefined() const { return dataType == UndefinedType; }
95 inline void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
96 inline QObject *getQObject() const { return qobjectValue; }
98 inline void setnumber(double v) { numberValue = v; dataType = NumberType; }
99 inline double getnumber() const { return numberValue; }
100 inline double &getnumberref() { return numberValue; }
102 inline void setfloat(float v) { floatValue = v; dataType = FloatType; }
103 inline float getfloat() const { return floatValue; }
104 inline float &getfloatref() { return floatValue; }
106 inline void setint(int v) { intValue = v; dataType = IntType; }
107 inline int getint() const { return intValue; }
108 inline int &getintref() { return intValue; }
110 inline void setbool(bool v) { boolValue = v; dataType = BoolType; }
111 inline bool getbool() const { return boolValue; }
112 inline bool &getboolref() { return boolValue; }
114 inline QVariant *getvariantptr() { return reinterpret_cast<QVariant *>(typeDataPtr()); }
115 inline QString *getstringptr() { return reinterpret_cast<QString *>(typeDataPtr()); }
116 inline QUrl *geturlptr() { return reinterpret_cast<QUrl *>(typeDataPtr()); }
117 inline v8::Handle<v8::Value> *gethandleptr() { return reinterpret_cast<v8::Handle<v8::Value> *>(typeDataPtr()); }
118 inline QJSValue *getjsvalueptr() { return reinterpret_cast<QJSValue *>(typeDataPtr()); }
120 inline const QVariant *getvariantptr() const { return reinterpret_cast<const QVariant *>(typeDataPtr()); }
121 inline const QString *getstringptr() const { return reinterpret_cast<const QString *>(typeDataPtr()); }
122 inline const QUrl *geturlptr() const { return reinterpret_cast<const QUrl *>(typeDataPtr()); }
123 inline const v8::Handle<v8::Value> *gethandleptr() const { return reinterpret_cast<const v8::Handle<v8::Value> *>(typeDataPtr()); }
124 inline const QJSValue *getjsvalueptr() const { return reinterpret_cast<const QJSValue *>(typeDataPtr()); }
126 size_t dataSize() { return sizeof(data); }
127 inline void *typeDataPtr() { return (void *)&data; }
128 inline void *typeMemory() { return (void *)data; }
129 inline const void *typeDataPtr() const { return (void *)&data; }
130 inline const void *typeMemory() const { return (void *)data; }
132 inline Type gettype() const { return dataType; }
133 inline void settype(Type t) { dataType = t; }
135 Type dataType; // Type of data
137 QObject *qobjectValue;
142 void *data[sizeof(QVariant)];
143 qint64 q_for_alignment_1;
144 double q_for_alignment_2;
147 inline void cleanup();
148 inline void cleanupString();
149 inline void cleanupUrl();
150 inline void cleanupColor();
151 inline void cleanupVariant();
152 inline void cleanupHandle();
153 inline void cleanupJSValue();
155 inline void copy(const Register &other);
156 inline void init(Type type);
157 #ifdef REGISTER_CLEANUP_DEBUG
163 if (dataType >= FirstCleanupType)
164 qWarning("Register leaked of type %d", dataType);
168 template <typename T>
169 inline static void copyConstructPointee(T *p, const T *other)
174 template <typename T>
175 inline static void defaultConstructPointee(T *p)
180 template <typename T>
181 inline static void destroyPointee(T *p)
187 void Register::cleanup()
189 if (dataType >= FirstCleanupType) {
190 if (dataType == QStringType) {
191 destroyPointee(getstringptr());
192 } else if (dataType == QUrlType) {
193 destroyPointee(geturlptr());
194 } else if (dataType == QColorType) {
195 QQml_valueTypeProvider()->destroyValueType(QMetaType::QColor, typeDataPtr(), dataSize());
196 } else if (dataType == QVariantType) {
197 destroyPointee(getvariantptr());
198 } else if (dataType == qMetaTypeId<v8::Handle<v8::Value> >()) {
199 destroyPointee(gethandleptr());
200 } else if (dataType == qMetaTypeId<QJSValue>()) {
201 destroyPointee(getjsvalueptr());
207 void Register::cleanupString()
209 destroyPointee(getstringptr());
213 void Register::cleanupUrl()
215 destroyPointee(geturlptr());
219 void Register::cleanupColor()
221 QQml_valueTypeProvider()->destroyValueType(QMetaType::QColor, typeDataPtr(), dataSize());
225 void Register::cleanupVariant()
227 destroyPointee(getvariantptr());
231 void Register::cleanupHandle()
233 destroyPointee(gethandleptr());
237 void Register::cleanupJSValue()
239 destroyPointee(getjsvalueptr());
243 void Register::copy(const Register &other)
246 if (other.dataType >= FirstCleanupType) {
247 if (other.dataType == QStringType)
248 copyConstructPointee(getstringptr(), other.getstringptr());
249 else if (other.dataType == QUrlType)
250 copyConstructPointee(geturlptr(), other.geturlptr());
251 else if (other.dataType == QColorType)
252 QQml_valueTypeProvider()->copyValueType(QMetaType::QColor, other.typeDataPtr(), typeDataPtr(), dataSize());
253 else if (other.dataType == QVariantType)
254 copyConstructPointee(getvariantptr(), other.getvariantptr());
255 else if (other.dataType == qMetaTypeId<v8::Handle<v8::Value> >())
256 copyConstructPointee(gethandleptr(), other.gethandleptr());
257 else if (other.dataType == qMetaTypeId<QJSValue>())
258 copyConstructPointee(getjsvalueptr(), other.getjsvalueptr());
262 void Register::init(Type type)
265 if (dataType >= FirstCleanupType) {
266 if (dataType == QStringType)
267 defaultConstructPointee(getstringptr());
268 else if (dataType == QUrlType)
269 defaultConstructPointee(geturlptr());
270 else if (dataType == QColorType)
271 QQml_valueTypeProvider()->initValueType(QMetaType::QColor, typeDataPtr(), dataSize());
272 else if (dataType == QVariantType)
273 defaultConstructPointee(getvariantptr());
274 else if (dataType == qMetaTypeId<v8::Handle<v8::Value> >())
275 defaultConstructPointee(gethandleptr());
276 else if (dataType == qMetaTypeId<QJSValue>())
277 defaultConstructPointee(getjsvalueptr());
281 } // end of anonymous namespace
283 QV4Bindings::QV4Bindings(const char *programData, QQmlContextData *context)
284 : subscriptions(0), program(0), bindings(0)
286 program = (QV4Program *)programData;
288 subscriptions = new Subscription[program->subscriptions];
289 bindings = new Binding[program->bindings];
291 QQmlAbstractExpression::setContext(context);
295 QV4Bindings::~QV4Bindings()
297 delete [] bindings; bindings = 0;
298 delete [] subscriptions; subscriptions = 0;
301 QQmlAbstractBinding *QV4Bindings::configBinding(QObject *target, QObject *scope,
302 const QQmlInstruction::instr_assignV4Binding *i)
304 Binding *rv = bindings + i->value;
311 addref(); // This is decremented in Binding::destroy()
316 void QV4Bindings::Binding::setEnabled(QQmlAbstractBinding *_This,
317 bool e, QQmlPropertyPrivate::WriteFlags flags)
319 QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This);
321 if (This->enabledFlag() != e) {
322 This->setEnabledFlag(e);
324 if (e) update(_This, flags);
328 void QV4Bindings::Binding::update(QQmlAbstractBinding *_This, QQmlPropertyPrivate::WriteFlags flags)
330 QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This);
331 This->parent->run(This, flags);
334 void QV4Bindings::Binding::destroy(QQmlAbstractBinding *_This)
336 QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This);
338 This->setEnabledFlag(false);
339 This->removeFromObject();
342 This->parent->release();
345 int QV4Bindings::Binding::propertyIndex(const QQmlAbstractBinding *_This)
347 const QV4Bindings::Binding *This = static_cast<const QV4Bindings::Binding *>(_This);
349 if (This->target.hasValue()) return This->target.constValue()->targetProperty;
350 else return This->instruction->property;
353 QObject *QV4Bindings::Binding::object(const QQmlAbstractBinding *_This)
355 const QV4Bindings::Binding *This = static_cast<const QV4Bindings::Binding *>(_This);
357 if (This->target.hasValue()) return This->target.constValue()->target;
358 return *This->target;
361 void QV4Bindings::Binding::retargetBinding(QQmlAbstractBinding *_This, QObject *t, int i)
363 QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This);
365 This->target.value().target = t;
366 This->target.value().targetProperty = i;
369 QV4Bindings::Subscription::Subscription()
370 : bindings(0), method(-1)
372 setCallback(QQmlNotifierEndpoint::QV4BindingsSubscription);
375 void QV4BindingsSubscription_callback(QQmlNotifierEndpoint *e, void **)
377 QV4Bindings::Subscription *s = static_cast<QV4Bindings::Subscription *>(e);
378 s->bindings->subscriptionNotify(s->method);
381 void QV4Bindings::subscriptionNotify(int id)
383 QV4Program::BindingReferenceList *list = program->signalTable(id);
385 for (quint32 ii = 0; ii < list->count; ++ii) {
386 QV4Program::BindingReference *bindingRef = list->bindings + ii;
388 Binding *binding = bindings + bindingRef->binding;
390 if (binding->executedBlocks & bindingRef->blockMask) {
391 run(binding, QQmlPropertyPrivate::DontRemoveBinding);
396 void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags)
398 if (!binding->enabledFlag())
401 QQmlContextData *context = QQmlAbstractExpression::context();
402 if (!context || !context->isValid())
405 // Check that the target has not been deleted
406 if (QQmlData::wasDeleted(*binding->target))
409 QQmlTrace trace("V4 Binding Update");
410 trace.addDetail("URL", context->url);
411 trace.addDetail("Line", binding->instruction->line);
412 trace.addDetail("Column", binding->instruction->column);
414 QQmlBindingProfiler prof(context->urlString, binding->instruction->line, binding->instruction->column, QQmlProfilerService::V4Binding);
416 const int propType = binding->instruction->propType;
417 const int property = binding->instruction->property;
419 if (binding->updatingFlag()) {
422 QQmlValueType *vt = QQmlValueTypeFactory::valueType(propType);
425 name = QLatin1String(binding->target->metaObject()->property(property & 0x0000FFFF).name());
426 name.append(QLatin1Char('.'));
427 name.append(QLatin1String(vt->metaObject()->property(property >> 16).name()));
429 name = QLatin1String(binding->target->metaObject()->property(property).name());
431 qmlInfo(*binding->target) << tr("Binding loop detected for property \"%1\"").arg(name);
435 int index = binding->instruction->value;
436 int fallbackIndex = binding->instruction->fallbackValue;
438 bool invalidated = false;
439 bool *inv = (fallbackIndex != -1) ? &invalidated : 0;
441 binding->setUpdatingFlag(true);
443 QQmlValueType *vt = QQmlValueTypeFactory::valueType(propType);
445 vt->read(*binding->target, property & 0x0000FFFF);
447 QObject *target = vt;
448 run(index, binding->executedBlocks, context, binding, binding->scope, target, flags, inv);
451 vt->write(*binding->target, property & 0x0000FFFF, flags);
454 QQmlData *data = QQmlData::get(*binding->target);
455 QQmlPropertyData *propertyData = (data && data->propertyCache ? data->propertyCache->property(property) : 0);
457 if (propertyData && propertyData->isVarProperty()) {
458 // We will allocate a V8 handle in this conversion/store
459 v8::HandleScope handle_scope;
460 v8::Context::Scope context_scope(QQmlEnginePrivate::get(context->engine)->v8engine()->context());
462 run(index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv);
464 run(index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv);
467 binding->setUpdatingFlag(false);
470 // This binding is no longer valid - fallback to V8
471 Q_ASSERT(fallbackIndex > -1);
472 QQmlAbstractBinding *b = QQmlPropertyPrivate::activateSharedBinding(context, fallbackIndex, flags);
473 Q_ASSERT(b == binding);
479 void QV4Bindings::unsubscribe(int subIndex)
481 Subscription *sub = (subscriptions + subIndex);
485 void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex)
487 unsubscribe(subIndex);
489 if (p->idValues[idIndex]) {
490 Subscription *sub = (subscriptions + subIndex);
491 sub->bindings = this;
492 sub->method = subIndex;
493 sub->connect(&p->idValues[idIndex].bindings);
497 void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex, QQmlEngine *e)
499 Subscription *sub = (subscriptions + subIndex);
500 if (sub->isConnected(o, notifyIndex))
502 sub->bindings = this;
503 sub->method = subIndex;
505 sub->connect(o, notifyIndex, e);
510 static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
512 QVariant qtscript = qtscriptRaw;
514 if (qtscript.userType() == v4.userType()) {
515 } else if (qtscript.canConvert(v4.userType())) {
516 qtscript.convert(v4.userType());
517 } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) {
518 qtscript = qVariantFromValue<QObject *>(0);
523 int type = qtscript.userType();
525 if (type == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
526 return QQmlMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData());
527 } else if (type == QMetaType::Double) {
529 double la = qvariant_cast<double>(qtscript);
530 double lr = qvariant_cast<double>(v4);
532 return la == lr || (qIsNaN(la) && qIsNaN(lr));
534 } else if (type == QMetaType::Float) {
536 float la = qvariant_cast<float>(qtscript);
537 float lr = qvariant_cast<float>(v4);
539 return la == lr || (qIsNaN(la) && qIsNaN(lr));
542 return qtscript == v4;
546 QByteArray testResultToString(const QVariant &result, bool undefined)
558 static void testBindingResult(const QString &binding, quint16 line, quint16 column,
559 QQmlContextData *context, QObject *scope,
560 const Register &result, int resultType)
562 QQmlExpression expression(context->asQQmlContext(), scope, binding);
563 bool isUndefined = false;
564 QVariant value = expression.evaluate(&isUndefined);
566 bool iserror = false;
567 QByteArray qtscriptResult;
570 const int handleType = qMetaTypeId<v8::Handle<v8::Value> >();
572 if (expression.hasError()) {
574 qtscriptResult = "exception";
575 } else if ((value.userType() != resultType) &&
576 (resultType != QMetaType::QVariant) &&
577 (resultType != handleType)) {
578 // Override the QMetaType conversions to make them more JS friendly.
579 if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
580 resultType == QMetaType::QUrl)) {
581 // number to string-like conversion.
582 value = QVariant::fromValue<QString>(QString::number(value.toDouble(), 'g', 16));
583 } else if (value.userType() == QMetaType::QUrl && resultType == QMetaType::Bool) {
584 // url to bool conversion
585 value = QVariant::fromValue<bool>(!value.toUrl().isEmpty());
588 if (!value.isNull() && !value.convert(resultType)) {
590 qtscriptResult = "exception";
591 } else if (resultType == QMetaType::QUrl) {
592 // a V8 value was converted to QUrl.
593 value = QVariant::fromValue<QUrl>(context->resolvedUrl(value.toUrl()));
598 qtscriptResult = testResultToString(value, isUndefined);
600 if (isUndefined && result.isUndefined()) {
602 } else if(isUndefined != result.isUndefined()) {
607 if (!result.isUndefined()) {
608 switch (resultType) {
609 case QMetaType::QString:
610 v4value = *result.getstringptr();
612 case QMetaType::QUrl:
613 v4value = *result.geturlptr();
615 case QMetaType::QObjectStar:
616 v4value = qVariantFromValue<QObject *>(result.getQObject());
618 case QMetaType::Bool:
619 v4value = result.getbool();
622 v4value = result.getint();
624 case QMetaType::Double:
625 v4value = result.getnumber();
627 case QMetaType::QColor:
628 v4value = QVariant(QMetaType::QColor, result.typeDataPtr());
630 case QMetaType::QVariant:
631 v4value = *result.getvariantptr();
634 if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
635 v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
636 } else if (resultType == handleType) {
637 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
638 v4value = ep->v8engine()->toVariant(*result.gethandleptr(), resultType);
641 v4Result = "Unknown V4 type";
645 if (v4Result.isEmpty())
646 v4Result = testResultToString(v4value, result.isUndefined());
648 if (!testCompareVariants(value, v4value))
652 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ':' << line << ':' << column;
654 qWarning().nospace() << " Binding: " << binding;
655 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
656 qWarning().nospace() << " V4: " << v4Result.constData();
660 static void testBindingException(const QString &binding, quint16 line, quint16 column,
661 QQmlContextData *context, QObject *scope)
663 QQmlExpression expression(context->asQQmlContext(), scope, binding);
664 bool isUndefined = false;
665 QVariant value = expression.evaluate(&isUndefined);
667 if (!expression.hasError()) {
668 QByteArray qtscriptResult = testResultToString(value, isUndefined);
669 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ':' << line << ':' << column;
670 qWarning().nospace() << " Binding: " << binding;
671 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
672 qWarning().nospace() << " V4: exception";
676 static void throwException(int id, QQmlDelayedError *error,
677 QV4Program *program, QQmlContextData *context,
678 const QString &description = QString())
680 if (description.isEmpty())
681 error->setErrorDescription(QLatin1String("TypeError: Result of expression is not an object"));
683 error->setErrorDescription(description);
685 quint32 e = *((quint32 *)(program->data() + program->exceptionDataOffset) + id);
686 error->setErrorLocation(context->url, (e >> 16), (e & 0xFFFF));
688 error->setErrorLocation(context->url, -1, -1);
690 if (!context->engine || !error->addError(QQmlEnginePrivate::get(context->engine)))
691 QQmlEnginePrivate::warning(context->engine, error);
694 const double QV4Bindings::D32 = 4294967296.0;
696 qint32 QV4Bindings::toInt32(double n)
698 if (qIsNaN(n) || qIsInf(n) || (n == 0))
701 double sign = (n < 0) ? -1.0 : 1.0;
702 double abs_n = fabs(n);
704 n = ::fmod(sign * ::floor(abs_n), D32);
705 const double D31 = D32 / 2.0;
707 if (sign == -1 && n < -D31)
710 else if (sign != -1 && n >= D31)
716 inline quint32 QV4Bindings::toUint32(double n)
718 if (qIsNaN(n) || qIsInf(n) || (n == 0))
721 double sign = (n < 0) ? -1.0 : 1.0;
722 double abs_n = fabs(n);
724 n = ::fmod(sign * ::floor(abs_n), D32);
732 #define THROW_EXCEPTION_STR(id, str) { \
733 if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \
734 throwException((id), error, program, context, (str)); \
735 goto exceptionExit; \
738 #define THROW_VALUE_EXCEPTION_STR(id, str) { \
739 throwException((id), error, program, context, (str)); \
740 goto exceptionExit; \
743 #define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
745 #define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
746 #define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg))
748 #define STRING_REGISTER(reg) { \
749 registers[(reg)].settype(QStringType); \
750 MARK_REGISTER(reg); \
753 #define URL_REGISTER(reg) { \
754 registers[(reg)].settype(QUrlType); \
755 MARK_REGISTER(reg); \
758 #define COLOR_REGISTER(reg) { \
759 registers[(reg)].settype(QColorType); \
760 MARK_REGISTER(reg); \
763 #define VARIANT_REGISTER(reg) { \
764 registers[(reg)].settype(QVariantType); \
765 MARK_REGISTER(reg); \
768 #define V8HANDLE_REGISTER(reg) { \
769 registers[(reg)].settype(V8HandleType); \
770 MARK_REGISTER(reg); \
773 #define JSVALUE_REGISTER(reg) { \
774 registers[(reg)].settype(QJSValueType); \
775 MARK_REGISTER(reg); \
778 //TODO: avoid construction of name and name-based lookup
779 #define INVALIDATION_CHECK(inv, obj, index) { \
781 QQmlData *data = QQmlData::get((obj)); \
782 if (data && !data->propertyCache) { \
783 data->propertyCache = QQmlEnginePrivate::get(context->engine)->cache(object); \
784 if (data->propertyCache) data->propertyCache->addref(); \
786 QQmlPropertyData *prop = (data && data->propertyCache) ? data->propertyCache->property((index)) : 0; \
787 if (prop && prop->isOverridden()) { \
788 int resolvedIndex = data->propertyCache->property(prop->name(obj))->coreIndex; \
789 if (index < resolvedIndex) { \
797 #ifdef QML_THREADED_INTERPRETER
798 void **QV4Bindings::getDecodeInstrTable()
800 static void **decode_instr;
802 QV4Bindings *dummy = new QV4Bindings(0, 0);
803 quint32 executedBlocks = 0;
804 dummy->run(0, executedBlocks, 0, 0, 0, 0,
805 QQmlPropertyPrivate::BypassInterceptor,
813 void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
814 QQmlContextData *context, QQmlDelayedError *error,
815 QObject *scope, QObject *output,
816 QQmlPropertyPrivate::WriteFlags storeFlags,
818 #ifdef QML_THREADED_INTERPRETER
823 #ifdef QML_THREADED_INTERPRETER
825 static void *decode_instr[] = {
826 FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR)
829 *table = decode_instr;
835 error->removeError();
837 Register registers[32];
838 quint32 cleanupRegisterMask = 0;
842 const char *code = program->instructions();
843 code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
844 const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
846 const char *data = program->data();
848 QString *testBindingSource = 0;
849 bool testBinding = false;
851 int bindingColumn = 0;
853 #ifdef QML_THREADED_INTERPRETER
854 goto *instr->common.code;
857 switch (instr->common.type) {
860 QML_V4_BEGIN_INSTR(Noop, common)
861 QML_V4_END_INSTR(Noop, common)
863 QML_V4_BEGIN_INSTR(BindingId, id)
864 bindingLine = instr->id.line;
865 bindingColumn = instr->id.column;
866 QML_V4_END_INSTR(BindingId, id)
868 QML_V4_BEGIN_INSTR(SubscribeId, subscribeop)
869 subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset);
870 QML_V4_END_INSTR(SubscribeId, subscribeop)
872 QML_V4_BEGIN_INSTR(Subscribe, subscribeop)
875 const Register &object = registers[instr->subscribeop.reg];
876 if (!object.isUndefined()) o = object.getQObject();
877 subscribe(o, instr->subscribeop.index, instr->subscribeop.offset, context->engine);
879 QML_V4_END_INSTR(Subscribe, subscribeop)
881 QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe)
883 Register ® = registers[instr->fetchAndSubscribe.reg];
885 if (reg.isUndefined())
886 THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
888 QObject *object = reg.getQObject();
890 THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
892 INVALIDATION_CHECK(invalidated, object, instr->fetchAndSubscribe.property.coreIndex);
894 int subIdx = instr->fetchAndSubscribe.subscription;
895 Subscription *sub = 0;
897 sub = (subscriptions + subIdx);
898 sub->bindings = this;
899 sub->method = subIdx;
902 const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType;
904 if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
905 MARK_REGISTER(instr->fetchAndSubscribe.reg);
906 QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
907 accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
910 if (valueType == FloatType) {
912 const double v = reg.getfloat();
916 if (accessors->notifier) {
917 QQmlNotifier *notifier = 0;
918 accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier);
919 if (notifier) sub->connect(notifier);
920 } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
921 sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex, context->engine);
925 QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
927 QML_V4_BEGIN_INSTR(LoadId, load)
928 registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
929 QML_V4_END_INSTR(LoadId, load)
931 QML_V4_BEGIN_INSTR(LoadScope, load)
932 registers[instr->load.reg].setQObject(scope);
933 QML_V4_END_INSTR(LoadScope, load)
935 QML_V4_BEGIN_INSTR(LoadRoot, load)
936 registers[instr->load.reg].setQObject(context->contextObject);
937 QML_V4_END_INSTR(LoadRoot, load)
939 QML_V4_BEGIN_INSTR(LoadModuleObject, load)
941 Register ® = registers[instr->load.reg];
943 const QString *name = reg.getstringptr();
944 QQmlTypeNameCache::Result r = context->imports->query(*name);
947 if (r.isValid() && r.importNamespace) {
948 QQmlMetaType::SingletonInstance *singletonType = context->imports->singletonType(r.importNamespace);
950 if (singletonType->qobjectCallback) {
951 singletonType->qobjectApi = singletonType->qobjectCallback(context->engine, context->engine);
952 singletonType->qobjectCallback = 0;
953 singletonType->scriptCallback = 0;
955 if (singletonType->qobjectApi)
956 reg.setQObject(singletonType->qobjectApi);
960 QML_V4_END_INSTR(LoadModuleObject, load)
962 QML_V4_BEGIN_INSTR(LoadAttached, attached)
964 const Register &input = registers[instr->attached.reg];
965 Register &output = registers[instr->attached.output];
966 if (input.isUndefined())
967 THROW_EXCEPTION(instr->attached.exceptionId);
969 QObject *object = registers[instr->attached.reg].getQObject();
971 output.setUndefined();
973 QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true);
975 output.setQObject(attached);
978 QML_V4_END_INSTR(LoadAttached, attached)
980 QML_V4_BEGIN_INSTR(UnaryNot, unaryop)
982 registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool());
984 QML_V4_END_INSTR(UnaryNot, unaryop)
986 QML_V4_BEGIN_INSTR(UnaryMinusNumber, unaryop)
988 registers[instr->unaryop.output].setnumber(-registers[instr->unaryop.src].getnumber());
990 QML_V4_END_INSTR(UnaryMinusNumber, unaryop)
992 QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
994 registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint());
996 QML_V4_END_INSTR(UnaryMinusInt, unaryop)
998 QML_V4_BEGIN_INSTR(UnaryPlusNumber, unaryop)
1000 registers[instr->unaryop.output].setnumber(+registers[instr->unaryop.src].getnumber());
1002 QML_V4_END_INSTR(UnaryPlusNumber, unaryop)
1004 QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
1006 registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint());
1008 QML_V4_END_INSTR(UnaryPlusInt, unaryop)
1010 QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop)
1012 const Register &src = registers[instr->unaryop.src];
1013 Register &output = registers[instr->unaryop.output];
1014 if (src.isUndefined()) output.setUndefined();
1015 else output.setint(src.getbool());
1017 QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
1019 QML_V4_BEGIN_INSTR(ConvertBoolToJSValue, unaryop)
1021 const Register &src = registers[instr->unaryop.src];
1022 Register &output = registers[instr->unaryop.output];
1023 if (src.isUndefined()) {
1024 output.setUndefined();
1026 new (output.getjsvalueptr()) QJSValue(src.getbool());
1027 JSVALUE_REGISTER(instr->unaryop.output);
1030 QML_V4_END_INSTR(ConvertBoolToJSValue, unaryop)
1032 QML_V4_BEGIN_INSTR(ConvertBoolToNumber, unaryop)
1034 const Register &src = registers[instr->unaryop.src];
1035 Register &output = registers[instr->unaryop.output];
1036 if (src.isUndefined()) output.setUndefined();
1037 else output.setnumber(src.getbool());
1039 QML_V4_END_INSTR(ConvertBoolToNumber, unaryop)
1041 QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
1043 const Register &src = registers[instr->unaryop.src];
1044 Register &output = registers[instr->unaryop.output];
1045 if (src.isUndefined()) {
1046 output.setUndefined();
1048 new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false"));
1049 STRING_REGISTER(instr->unaryop.output);
1052 QML_V4_END_INSTR(ConvertBoolToString, unaryop)
1054 QML_V4_BEGIN_INSTR(ConvertBoolToVariant, unaryop)
1056 const Register &src = registers[instr->unaryop.src];
1057 Register &output = registers[instr->unaryop.output];
1058 if (src.isUndefined()) {
1059 output.setUndefined();
1061 new (output.getvariantptr()) QVariant(src.getbool());
1062 VARIANT_REGISTER(instr->unaryop.output);
1065 QML_V4_END_INSTR(ConvertBoolToVariant, unaryop)
1067 QML_V4_BEGIN_INSTR(ConvertBoolToVar, unaryop)
1069 const Register &src = registers[instr->unaryop.src];
1070 Register &output = registers[instr->unaryop.output];
1071 if (src.isUndefined()) {
1072 output.setUndefined();
1074 new (output.gethandleptr()) v8::Handle<v8::Value>(v8::Boolean::New(src.getbool()));
1075 V8HANDLE_REGISTER(instr->unaryop.output);
1078 QML_V4_END_INSTR(ConvertBoolToVar, unaryop)
1080 QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
1082 const Register &src = registers[instr->unaryop.src];
1083 Register &output = registers[instr->unaryop.output];
1084 if (src.isUndefined()) output.setUndefined();
1085 else output.setbool(src.getint());
1087 QML_V4_END_INSTR(ConvertIntToBool, unaryop)
1089 QML_V4_BEGIN_INSTR(ConvertIntToJSValue, unaryop)
1091 const Register &src = registers[instr->unaryop.src];
1092 Register &output = registers[instr->unaryop.output];
1093 if (src.isUndefined()) {
1094 output.setUndefined();
1096 new (output.getjsvalueptr()) QJSValue(src.getint());
1097 JSVALUE_REGISTER(instr->unaryop.output);
1100 QML_V4_END_INSTR(ConvertIntToJSValue, unaryop)
1102 QML_V4_BEGIN_INSTR(ConvertIntToNumber, unaryop)
1104 const Register &src = registers[instr->unaryop.src];
1105 Register &output = registers[instr->unaryop.output];
1106 if (src.isUndefined()) output.setUndefined();
1107 else output.setnumber(double(src.getint()));
1109 QML_V4_END_INSTR(ConvertIntToNumber, unaryop)
1111 QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
1113 const Register &src = registers[instr->unaryop.src];
1114 Register &output = registers[instr->unaryop.output];
1115 if (src.isUndefined()) {
1116 output.setUndefined();
1118 new (output.getstringptr()) QString(QString::number(src.getint()));
1119 STRING_REGISTER(instr->unaryop.output);
1122 QML_V4_END_INSTR(ConvertIntToString, unaryop)
1124 QML_V4_BEGIN_INSTR(ConvertIntToVariant, unaryop)
1126 const Register &src = registers[instr->unaryop.src];
1127 Register &output = registers[instr->unaryop.output];
1128 if (src.isUndefined()) {
1129 output.setUndefined();
1131 new (output.getvariantptr()) QVariant(src.getint());
1132 VARIANT_REGISTER(instr->unaryop.output);
1135 QML_V4_END_INSTR(ConvertIntToVariant, unaryop)
1137 QML_V4_BEGIN_INSTR(ConvertIntToVar, unaryop)
1139 const Register &src = registers[instr->unaryop.src];
1140 Register &output = registers[instr->unaryop.output];
1141 if (src.isUndefined()) {
1142 output.setUndefined();
1144 new (output.gethandleptr()) v8::Handle<v8::Value>(v8::Integer::New(src.getint()));
1145 V8HANDLE_REGISTER(instr->unaryop.output);
1148 QML_V4_END_INSTR(ConvertIntToVar, unaryop)
1150 QML_V4_BEGIN_INSTR(ConvertJSValueToVar, unaryop)
1152 const Register &src = registers[instr->unaryop.src];
1153 Register &output = registers[instr->unaryop.output];
1154 if (src.isUndefined()) {
1155 output.setUndefined();
1157 QJSValue tmp(*src.getjsvalueptr());
1158 if (instr->unaryop.src == instr->unaryop.output) {
1159 output.cleanupJSValue();
1160 MARK_CLEAN_REGISTER(instr->unaryop.output);
1162 if (tmp.isUndefined()) {
1163 output.setUndefined();
1165 QV8Engine *v8engine = QQmlEnginePrivate::get(context->engine)->v8engine();
1166 new (output.gethandleptr()) v8::Handle<v8::Value>(
1167 QJSValuePrivate::get(tmp)->asV8Value(v8engine));
1168 V8HANDLE_REGISTER(instr->unaryop.output);
1172 QML_V4_END_INSTR(ConvertJSValueToVar, unaryop)
1174 QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
1176 const Register &src = registers[instr->unaryop.src];
1177 Register &output = registers[instr->unaryop.output];
1178 if (src.isUndefined()) output.setUndefined();
1179 else output.setbool(src.getnumber() != 0);
1181 QML_V4_END_INSTR(ConvertNumberToBool, unaryop)
1183 QML_V4_BEGIN_INSTR(ConvertNumberToInt, unaryop)
1185 const Register &src = registers[instr->unaryop.src];
1186 Register &output = registers[instr->unaryop.output];
1187 if (src.isUndefined()) output.setUndefined();
1188 else output.setint(toInt32(src.getnumber()));
1190 QML_V4_END_INSTR(ConvertNumberToInt, unaryop)
1192 QML_V4_BEGIN_INSTR(ConvertNumberToJSValue, unaryop)
1194 const Register &src = registers[instr->unaryop.src];
1195 Register &output = registers[instr->unaryop.output];
1196 if (src.isUndefined()) {
1197 output.setUndefined();
1199 new (output.getjsvalueptr()) QJSValue(src.getnumber());
1200 JSVALUE_REGISTER(instr->unaryop.output);
1203 QML_V4_END_INSTR(ConvertNumberToJSValue, unaryop)
1205 QML_V4_BEGIN_INSTR(ConvertNumberToString, unaryop)
1207 const Register &src = registers[instr->unaryop.src];
1208 Register &output = registers[instr->unaryop.output];
1210 if (src.isUndefined()) {
1211 output.setUndefined();
1213 new (output.getstringptr()) QString(QString::number(src.getnumber(), 'g', 16));
1214 STRING_REGISTER(instr->unaryop.output);
1217 QML_V4_END_INSTR(ConvertNumberToString, unaryop)
1219 QML_V4_BEGIN_INSTR(ConvertNumberToVariant, unaryop)
1221 const Register &src = registers[instr->unaryop.src];
1222 Register &output = registers[instr->unaryop.output];
1223 if (src.isUndefined()) {
1224 output.setUndefined();
1226 new (output.getvariantptr()) QVariant(src.getnumber());
1227 VARIANT_REGISTER(instr->unaryop.output);
1230 QML_V4_END_INSTR(ConvertNumberToVariant, unaryop)
1232 QML_V4_BEGIN_INSTR(ConvertNumberToVar, unaryop)
1234 const Register &src = registers[instr->unaryop.src];
1235 Register &output = registers[instr->unaryop.output];
1236 if (src.isUndefined()) {
1237 output.setUndefined();
1239 new (output.gethandleptr()) v8::Handle<v8::Value>(v8::Number::New(src.getnumber()));
1240 V8HANDLE_REGISTER(instr->unaryop.output);
1243 QML_V4_END_INSTR(ConvertNumberToVar, unaryop)
1245 QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
1247 const Register &src = registers[instr->unaryop.src];
1248 Register &output = registers[instr->unaryop.output];
1250 if (src.isUndefined()) {
1251 output.setUndefined();
1253 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1254 // Ideally we should just call the methods in the QScript namespace directly.
1255 QJSValue tmp(*src.getstringptr());
1256 if (instr->unaryop.src == instr->unaryop.output) {
1257 output.cleanupString();
1258 MARK_CLEAN_REGISTER(instr->unaryop.output);
1260 output.setbool(tmp.toBool());
1263 QML_V4_END_INSTR(ConvertStringToBool, unaryop)
1265 QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop)
1267 const Register &src = registers[instr->unaryop.src];
1268 Register &output = registers[instr->unaryop.output];
1270 if (src.isUndefined()) {
1271 output.setUndefined();
1273 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1274 // Ideally we should just call the methods in the QScript namespace directly.
1275 QJSValue tmp(*src.getstringptr());
1276 if (instr->unaryop.src == instr->unaryop.output) {
1277 output.cleanupString();
1278 MARK_CLEAN_REGISTER(instr->unaryop.output);
1280 output.setint(tmp.toInt());
1283 QML_V4_END_INSTR(ConvertStringToInt, unaryop)
1285 QML_V4_BEGIN_INSTR(ConvertStringToJSValue, unaryop)
1287 const Register &src = registers[instr->unaryop.src];
1288 Register &output = registers[instr->unaryop.output];
1289 if (src.isUndefined()) {
1290 output.setUndefined();
1292 QString tmp(*src.getstringptr());
1293 if (instr->unaryop.src == instr->unaryop.output) {
1294 output.cleanupString();
1295 MARK_CLEAN_REGISTER(instr->unaryop.output);
1297 new (output.getjsvalueptr()) QJSValue(tmp);
1298 JSVALUE_REGISTER(instr->unaryop.output);
1301 QML_V4_END_INSTR(ConvertStringToJSValue, unaryop)
1303 QML_V4_BEGIN_INSTR(ConvertStringToNumber, unaryop)
1305 const Register &src = registers[instr->unaryop.src];
1306 Register &output = registers[instr->unaryop.output];
1308 if (src.isUndefined()) {
1309 output.setUndefined();
1311 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1312 // Ideally we should just call the methods in the QScript namespace directly.
1313 QJSValue tmp(*src.getstringptr());
1314 if (instr->unaryop.src == instr->unaryop.output) {
1315 output.cleanupString();
1316 MARK_CLEAN_REGISTER(instr->unaryop.output);
1318 output.setnumber(tmp.toNumber());
1321 QML_V4_END_INSTR(ConvertStringToNumber, unaryop)
1323 QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
1325 const Register &src = registers[instr->unaryop.src];
1326 Register &output = registers[instr->unaryop.output];
1328 if (src.isUndefined()) {
1329 output.setUndefined();
1331 QString tmp(*src.getstringptr());
1332 // Encoded dir-separators defeat QUrl processing - decode them first
1333 tmp.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
1334 if (instr->unaryop.src == instr->unaryop.output) {
1335 output.cleanupString();
1336 MARK_CLEAN_REGISTER(instr->unaryop.output);
1338 new (output.geturlptr()) QUrl(tmp);
1340 URL_REGISTER(instr->unaryop.output);
1343 QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
1345 QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop)
1347 const Register &src = registers[instr->unaryop.src];
1348 Register &output = registers[instr->unaryop.output];
1350 if (src.isUndefined()) {
1351 output.setUndefined();
1353 const QString tmp(*src.getstringptr());
1354 if (instr->unaryop.src == instr->unaryop.output) {
1355 output.cleanupString();
1356 MARK_CLEAN_REGISTER(instr->unaryop.output);
1358 QQml_valueTypeProvider()->createValueFromString(QMetaType::QColor, tmp, output.typeDataPtr(), output.dataSize());
1360 COLOR_REGISTER(instr->unaryop.output);
1363 QML_V4_END_INSTR(ConvertStringToColor, unaryop)
1365 QML_V4_BEGIN_INSTR(ConvertStringToVariant, unaryop)
1367 const Register &src = registers[instr->unaryop.src];
1368 Register &output = registers[instr->unaryop.output];
1369 if (src.isUndefined()) {
1370 output.setUndefined();
1372 const QString tmp(*src.getstringptr());
1373 if (instr->unaryop.src == instr->unaryop.output) {
1374 output.cleanupString();
1375 MARK_CLEAN_REGISTER(instr->unaryop.output);
1377 new (output.getvariantptr()) QVariant(tmp);
1379 VARIANT_REGISTER(instr->unaryop.output);
1382 QML_V4_END_INSTR(ConvertStringToVariant, unaryop)
1384 QML_V4_BEGIN_INSTR(ConvertStringToVar, unaryop)
1386 const Register &src = registers[instr->unaryop.src];
1387 Register &output = registers[instr->unaryop.output];
1388 if (src.isUndefined()) {
1389 output.setUndefined();
1391 const QString tmp(*src.getstringptr());
1392 if (instr->unaryop.src == instr->unaryop.output) {
1393 output.cleanupString();
1394 MARK_CLEAN_REGISTER(instr->unaryop.output);
1396 new (output.gethandleptr()) v8::Handle<v8::Value>(QJSConverter::toString(tmp));
1397 V8HANDLE_REGISTER(instr->unaryop.output);
1400 QML_V4_END_INSTR(ConvertStringToVar, unaryop)
1402 QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
1404 const Register &src = registers[instr->unaryop.src];
1405 Register &output = registers[instr->unaryop.output];
1407 if (src.isUndefined()) {
1408 output.setUndefined();
1410 const QUrl tmp(*src.geturlptr());
1411 if (instr->unaryop.src == instr->unaryop.output) {
1412 output.cleanupUrl();
1413 MARK_CLEAN_REGISTER(instr->unaryop.output);
1415 output.setbool(!tmp.isEmpty());
1418 QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
1420 QML_V4_BEGIN_INSTR(ConvertUrlToJSValue, unaryop)
1422 const Register &src = registers[instr->unaryop.src];
1423 Register &output = registers[instr->unaryop.output];
1424 if (src.isUndefined()) {
1425 output.setUndefined();
1427 const QUrl tmp(*src.geturlptr());
1428 if (instr->unaryop.src == instr->unaryop.output) {
1429 output.cleanupUrl();
1430 MARK_CLEAN_REGISTER(instr->unaryop.output);
1432 new (output.getjsvalueptr()) QJSValue(tmp.toString());
1433 JSVALUE_REGISTER(instr->unaryop.output);
1436 QML_V4_END_INSTR(ConvertUrlToJSValue, unaryop)
1438 QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
1440 const Register &src = registers[instr->unaryop.src];
1441 Register &output = registers[instr->unaryop.output];
1443 if (src.isUndefined()) {
1444 output.setUndefined();
1446 const QUrl tmp(*src.geturlptr());
1447 if (instr->unaryop.src == instr->unaryop.output) {
1448 output.cleanupUrl();
1449 MARK_CLEAN_REGISTER(instr->unaryop.output);
1451 new (output.getstringptr()) QString(tmp.toString());
1452 STRING_REGISTER(instr->unaryop.output);
1455 QML_V4_END_INSTR(ConvertUrlToString, unaryop)
1457 QML_V4_BEGIN_INSTR(ConvertUrlToVariant, unaryop)
1459 const Register &src = registers[instr->unaryop.src];
1460 Register &output = registers[instr->unaryop.output];
1462 if (src.isUndefined()) {
1463 output.setUndefined();
1465 const QUrl tmp(*src.geturlptr());
1466 if (instr->unaryop.src == instr->unaryop.output) {
1467 output.cleanupUrl();
1468 MARK_CLEAN_REGISTER(instr->unaryop.output);
1470 new (output.getvariantptr()) QVariant(tmp);
1471 VARIANT_REGISTER(instr->unaryop.output);
1474 QML_V4_END_INSTR(ConvertUrlToVariant, unaryop)
1476 QML_V4_BEGIN_INSTR(ConvertUrlToVar, unaryop)
1478 const Register &src = registers[instr->unaryop.src];
1479 Register &output = registers[instr->unaryop.output];
1481 if (src.isUndefined()) {
1482 output.setUndefined();
1484 const QUrl tmp(*src.geturlptr());
1485 if (instr->unaryop.src == instr->unaryop.output) {
1486 output.cleanupUrl();
1487 MARK_CLEAN_REGISTER(instr->unaryop.output);
1489 new (output.gethandleptr()) v8::Handle<v8::Value>(QJSConverter::toString(tmp.toString()));
1490 V8HANDLE_REGISTER(instr->unaryop.output);
1493 QML_V4_END_INSTR(ConvertUrlToVar, unaryop)
1495 QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
1497 const Register &src = registers[instr->unaryop.src];
1498 Register &output = registers[instr->unaryop.output];
1500 if (src.isUndefined()) {
1501 output.setUndefined();
1503 // for compatibility with color behavior in v8, always true
1504 output.setbool(true);
1507 QML_V4_END_INSTR(ConvertColorToBool, unaryop)
1509 QML_V4_BEGIN_INSTR(ConvertColorToJSValue, unaryop)
1511 const Register &src = registers[instr->unaryop.src];
1512 Register &output = registers[instr->unaryop.output];
1513 if (src.isUndefined()) {
1514 output.setUndefined();
1516 const QVariant tmp(QMetaType::QColor, src.typeDataPtr());
1517 if (instr->unaryop.src == instr->unaryop.output) {
1518 output.cleanupColor();
1519 MARK_CLEAN_REGISTER(instr->unaryop.output);
1522 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
1523 QV8Engine *v8engine = ep->v8engine();
1524 QQmlValueType *vt = QQmlValueTypeFactory::valueType(QMetaType::QColor);
1525 v8::HandleScope handle_scope;
1526 v8::Context::Scope scope(v8engine->context());
1527 new (output.getjsvalueptr()) QJSValue(v8engine->scriptValueFromInternal(
1528 v8engine->valueTypeWrapper()->newValueType(tmp, vt)));
1529 JSVALUE_REGISTER(instr->unaryop.output);
1532 QML_V4_END_INSTR(ConvertColorToJSValue, unaryop)
1534 QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop)
1536 const Register &src = registers[instr->unaryop.src];
1537 Register &output = registers[instr->unaryop.output];
1539 if (src.isUndefined()) {
1540 output.setUndefined();
1542 QQml_valueTypeProvider()->createStringFromValue(QMetaType::QColor, src.typeDataPtr(), output.getstringptr());
1543 STRING_REGISTER(instr->unaryop.output);
1546 QML_V4_END_INSTR(ConvertColorToString, unaryop)
1548 QML_V4_BEGIN_INSTR(ConvertColorToVariant, unaryop)
1550 const Register &src = registers[instr->unaryop.src];
1551 Register &output = registers[instr->unaryop.output];
1553 if (src.isUndefined()) {
1554 output.setUndefined();
1556 QVariant tmp(QMetaType::QColor, src.typeDataPtr());
1557 if (instr->unaryop.src == instr->unaryop.output) {
1558 output.cleanupColor();
1559 MARK_CLEAN_REGISTER(instr->unaryop.output);
1561 new (output.getvariantptr()) QVariant(tmp);
1562 VARIANT_REGISTER(instr->unaryop.output);
1565 QML_V4_END_INSTR(ConvertColorToVariant, unaryop)
1567 QML_V4_BEGIN_INSTR(ConvertColorToVar, unaryop)
1569 const Register &src = registers[instr->unaryop.src];
1570 Register &output = registers[instr->unaryop.output];
1572 if (src.isUndefined()) {
1573 output.setUndefined();
1575 const QVariant tmp(QMetaType::QColor, src.typeDataPtr());
1576 if (instr->unaryop.src == instr->unaryop.output) {
1577 output.cleanupColor();
1578 MARK_CLEAN_REGISTER(instr->unaryop.output);
1581 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
1582 QQmlValueType *vt = QQmlValueTypeFactory::valueType(QMetaType::QColor);
1583 new (output.gethandleptr()) v8::Handle<v8::Value>(ep->v8engine()->valueTypeWrapper()->newValueType(tmp, vt));
1584 V8HANDLE_REGISTER(instr->unaryop.output);
1587 QML_V4_END_INSTR(ConvertColorToVar, unaryop)
1589 QML_V4_BEGIN_INSTR(ConvertObjectToBool, unaryop)
1591 const Register &src = registers[instr->unaryop.src];
1592 Register &output = registers[instr->unaryop.output];
1594 if (src.isUndefined())
1595 output.setUndefined();
1597 output.setbool(src.getQObject() != 0);
1599 QML_V4_END_INSTR(ConvertObjectToBool, unaryop)
1601 QML_V4_BEGIN_INSTR(ConvertObjectToJSValue, unaryop)
1603 const Register &src = registers[instr->unaryop.src];
1604 Register &output = registers[instr->unaryop.output];
1605 if (src.isUndefined()) {
1606 output.setUndefined();
1608 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
1609 v8::HandleScope handle_scope;
1610 v8::Context::Scope scope(ep->v8engine()->context());
1611 new (output.getjsvalueptr()) QJSValue(context->engine->newQObject(src.getQObject()));
1612 JSVALUE_REGISTER(instr->unaryop.output);
1615 QML_V4_END_INSTR(ConvertObjectToJSValue, unaryop)
1617 QML_V4_BEGIN_INSTR(ConvertObjectToVariant, unaryop)
1619 const Register &src = registers[instr->unaryop.src];
1620 Register &output = registers[instr->unaryop.output];
1622 if (src.isUndefined())
1623 output.setUndefined();
1625 new (output.getvariantptr()) QVariant(qVariantFromValue<QObject *>(src.getQObject()));
1626 VARIANT_REGISTER(instr->unaryop.output);
1629 QML_V4_END_INSTR(ConvertObjectToVariant, unaryop)
1631 QML_V4_BEGIN_INSTR(ConvertObjectToVar, unaryop)
1633 const Register &src = registers[instr->unaryop.src];
1634 Register &output = registers[instr->unaryop.output];
1636 if (src.isUndefined())
1637 output.setUndefined();
1639 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
1640 new (output.gethandleptr()) v8::Handle<v8::Value>(ep->v8engine()->newQObject(src.getQObject()));
1641 V8HANDLE_REGISTER(instr->unaryop.output);
1644 QML_V4_END_INSTR(ConvertObjectToVar, unaryop)
1646 QML_V4_BEGIN_INSTR(ConvertVarToJSValue, unaryop)
1648 const Register &src = registers[instr->unaryop.src];
1649 Register &output = registers[instr->unaryop.output];
1650 if (src.isUndefined()) {
1651 output.setUndefined();
1653 v8::Handle<v8::Value> tmp(*src.gethandleptr());
1654 if (instr->unaryop.src == instr->unaryop.output) {
1655 output.cleanupHandle();
1656 MARK_CLEAN_REGISTER(instr->unaryop.output);
1658 QV8Engine *v8engine = QQmlEnginePrivate::get(context->engine)->v8engine();
1659 new (output.getjsvalueptr()) QJSValue(v8engine->scriptValueFromInternal(tmp));
1660 JSVALUE_REGISTER(instr->unaryop.output);
1663 QML_V4_END_INSTR(ConvertVarToJSValue, unaryop)
1665 QML_V4_BEGIN_INSTR(ConvertNullToJSValue, unaryop)
1667 Register &output = registers[instr->unaryop.output];
1668 new (output.getjsvalueptr()) QJSValue(QJSValue::NullValue);
1669 JSVALUE_REGISTER(instr->unaryop.output);
1671 QML_V4_END_INSTR(ConvertNullToJSValue, unaryop)
1673 QML_V4_BEGIN_INSTR(ConvertNullToObject, unaryop)
1675 Register &output = registers[instr->unaryop.output];
1676 output.setQObject(0);
1678 QML_V4_END_INSTR(ConvertNullToObject, unaryop)
1680 QML_V4_BEGIN_INSTR(ConvertNullToVariant, unaryop)
1682 Register &output = registers[instr->unaryop.output];
1683 new (output.getvariantptr()) QVariant();
1684 VARIANT_REGISTER(instr->unaryop.output);
1686 QML_V4_END_INSTR(ConvertNullToVariant, unaryop)
1688 QML_V4_BEGIN_INSTR(ConvertNullToVar, unaryop)
1690 Register &output = registers[instr->unaryop.output];
1691 new (output.gethandleptr()) v8::Handle<v8::Value>(v8::Null());
1692 V8HANDLE_REGISTER(instr->unaryop.output);
1694 QML_V4_END_INSTR(ConvertNullToVar, unaryop)
1696 QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
1698 const Register &src = registers[instr->unaryop.src];
1699 Register &output = registers[instr->unaryop.output];
1700 if (src.isUndefined()) {
1701 output.setUndefined();
1703 const QUrl tmp(*src.geturlptr());
1704 if (instr->unaryop.src == instr->unaryop.output) {
1705 *output.geturlptr() = context->resolvedUrl(tmp);
1707 new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
1708 URL_REGISTER(instr->unaryop.output);
1712 QML_V4_END_INSTR(ResolveUrl, unaryop)
1714 QML_V4_BEGIN_INSTR(MathSinNumber, unaryop)
1716 const Register &src = registers[instr->unaryop.src];
1717 Register &output = registers[instr->unaryop.output];
1718 if (src.isUndefined()) output.setUndefined();
1719 else output.setnumber(qSin(src.getnumber()));
1721 QML_V4_END_INSTR(MathSinNumber, unaryop)
1723 QML_V4_BEGIN_INSTR(MathCosNumber, unaryop)
1725 const Register &src = registers[instr->unaryop.src];
1726 Register &output = registers[instr->unaryop.output];
1727 if (src.isUndefined()) output.setUndefined();
1728 else output.setnumber(qCos(src.getnumber()));
1730 QML_V4_END_INSTR(MathCosNumber, unaryop)
1732 QML_V4_BEGIN_INSTR(MathAbsNumber, unaryop)
1734 const Register &src = registers[instr->unaryop.src];
1735 Register &output = registers[instr->unaryop.output];
1736 if (src.isUndefined()) output.setUndefined();
1737 else output.setnumber(qAbs(src.getnumber()));
1739 QML_V4_END_INSTR(MathAbsNumber, unaryop)
1741 QML_V4_BEGIN_INSTR(MathRoundNumber, unaryop)
1743 const Register &src = registers[instr->unaryop.src];
1744 Register &output = registers[instr->unaryop.output];
1745 if (src.isUndefined()) output.setUndefined();
1746 else output.setint(qRound(src.getnumber()));
1748 QML_V4_END_INSTR(MathRoundNumber, unaryop)
1750 QML_V4_BEGIN_INSTR(MathFloorNumber, unaryop)
1752 const Register &src = registers[instr->unaryop.src];
1753 Register &output = registers[instr->unaryop.output];
1754 if (src.isUndefined()) output.setUndefined();
1755 else output.setint(qFloor(src.getnumber()));
1757 QML_V4_END_INSTR(MathFloorNumber, unaryop)
1759 QML_V4_BEGIN_INSTR(MathCeilNumber, unaryop)
1761 const Register &src = registers[instr->unaryop.src];
1762 Register &output = registers[instr->unaryop.output];
1763 if (src.isUndefined()) output.setUndefined();
1764 else output.setint(qCeil(src.getnumber()));
1766 QML_V4_END_INSTR(MathCeilNumber, unaryop)
1768 QML_V4_BEGIN_INSTR(MathPINumber, unaryop)
1770 static const double qmlPI = 2.0 * qAsin(1.0);
1771 Register &output = registers[instr->unaryop.output];
1772 output.setnumber(qmlPI);
1774 QML_V4_END_INSTR(MathPINumber, unaryop)
1776 QML_V4_BEGIN_INSTR(LoadNull, null_value)
1777 registers[instr->null_value.reg].setNull();
1778 QML_V4_END_INSTR(LoadNull, null_value)
1780 QML_V4_BEGIN_INSTR(LoadNumber, number_value)
1781 registers[instr->number_value.reg].setnumber(instr->number_value.value);
1782 QML_V4_END_INSTR(LoadNumber, number_value)
1784 QML_V4_BEGIN_INSTR(LoadInt, int_value)
1785 registers[instr->int_value.reg].setint(instr->int_value.value);
1786 QML_V4_END_INSTR(LoadInt, int_value)
1788 QML_V4_BEGIN_INSTR(LoadBool, bool_value)
1789 registers[instr->bool_value.reg].setbool(instr->bool_value.value);
1790 QML_V4_END_INSTR(LoadBool, bool_value)
1792 QML_V4_BEGIN_INSTR(LoadString, string_value)
1794 Register &output = registers[instr->string_value.reg];
1795 QChar *string = (QChar *)(data + instr->string_value.offset);
1796 new (output.getstringptr()) QString(string, instr->string_value.length);
1797 STRING_REGISTER(instr->string_value.reg);
1799 QML_V4_END_INSTR(LoadString, string_value)
1801 QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
1803 testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
1806 QML_V4_END_INSTR(String, string_value)
1808 QML_V4_BEGIN_INSTR(BitAndInt, binaryop)
1810 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() &
1811 registers[instr->binaryop.right].getint());
1813 QML_V4_END_INSTR(BitAndInt, binaryop)
1815 QML_V4_BEGIN_INSTR(BitOrInt, binaryop)
1817 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() |
1818 registers[instr->binaryop.right].getint());
1820 QML_V4_END_INSTR(BitAndInt, binaryop)
1822 QML_V4_BEGIN_INSTR(BitXorInt, binaryop)
1824 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^
1825 registers[instr->binaryop.right].getint());
1827 QML_V4_END_INSTR(BitXorInt, binaryop)
1829 QML_V4_BEGIN_INSTR(AddNumber, binaryop)
1831 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() +
1832 registers[instr->binaryop.right].getnumber());
1834 QML_V4_END_INSTR(AddNumber, binaryop)
1836 QML_V4_BEGIN_INSTR(AddString, binaryop)
1838 QString &string = *registers[instr->binaryop.output].getstringptr();
1839 if (instr->binaryop.output == instr->binaryop.left) {
1840 string += registers[instr->binaryop.right].getstringptr();
1842 string = *registers[instr->binaryop.left].getstringptr() +
1843 *registers[instr->binaryop.right].getstringptr();
1846 QML_V4_END_INSTR(AddString, binaryop)
1848 QML_V4_BEGIN_INSTR(SubNumber, binaryop)
1850 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() -
1851 registers[instr->binaryop.right].getnumber());
1853 QML_V4_END_INSTR(SubNumber, binaryop)
1855 QML_V4_BEGIN_INSTR(MulNumber, binaryop)
1857 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() *
1858 registers[instr->binaryop.right].getnumber());
1860 QML_V4_END_INSTR(MulNumber, binaryop)
1862 QML_V4_BEGIN_INSTR(DivNumber, binaryop)
1864 registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() /
1865 registers[instr->binaryop.right].getnumber());
1867 QML_V4_END_INSTR(DivNumber, binaryop)
1869 QML_V4_BEGIN_INSTR(ModNumber, binaryop)
1871 Register &target = registers[instr->binaryop.output];
1872 const Register &left = registers[instr->binaryop.left];
1873 const Register &right = registers[instr->binaryop.right];
1874 target.setnumber(::fmod(left.getnumber(), right.getnumber()));
1876 QML_V4_END_INSTR(ModInt, binaryop)
1878 QML_V4_BEGIN_INSTR(LShiftInt, binaryop)
1880 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() <<
1881 registers[instr->binaryop.right].getint());
1883 QML_V4_END_INSTR(LShiftInt, binaryop)
1885 QML_V4_BEGIN_INSTR(RShiftInt, binaryop)
1887 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >>
1888 registers[instr->binaryop.right].getint());
1890 QML_V4_END_INSTR(RShiftInt, binaryop)
1892 QML_V4_BEGIN_INSTR(URShiftInt, binaryop)
1894 registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >>
1895 registers[instr->binaryop.right].getint());
1897 QML_V4_END_INSTR(URShiftInt, binaryop)
1899 QML_V4_BEGIN_INSTR(GtNumber, binaryop)
1901 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >
1902 registers[instr->binaryop.right].getnumber());
1904 QML_V4_END_INSTR(GtNumber, binaryop)
1906 QML_V4_BEGIN_INSTR(LtNumber, binaryop)
1908 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <
1909 registers[instr->binaryop.right].getnumber());
1911 QML_V4_END_INSTR(LtNumber, binaryop)
1913 QML_V4_BEGIN_INSTR(GeNumber, binaryop)
1915 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >=
1916 registers[instr->binaryop.right].getnumber());
1918 QML_V4_END_INSTR(GeNumber, binaryop)
1920 QML_V4_BEGIN_INSTR(LeNumber, binaryop)
1922 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <=
1923 registers[instr->binaryop.right].getnumber());
1925 QML_V4_END_INSTR(LeNumber, binaryop)
1927 QML_V4_BEGIN_INSTR(EqualNumber, binaryop)
1929 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
1930 registers[instr->binaryop.right].getnumber());
1932 QML_V4_END_INSTR(EqualNumber, binaryop)
1934 QML_V4_BEGIN_INSTR(NotEqualNumber, binaryop)
1936 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
1937 registers[instr->binaryop.right].getnumber());
1939 QML_V4_END_INSTR(NotEqualNumber, binaryop)
1941 QML_V4_BEGIN_INSTR(StrictEqualNumber, binaryop)
1943 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
1944 registers[instr->binaryop.right].getnumber());
1946 QML_V4_END_INSTR(StrictEqualNumber, binaryop)
1948 QML_V4_BEGIN_INSTR(StrictNotEqualNumber, binaryop)
1950 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
1951 registers[instr->binaryop.right].getnumber());
1953 QML_V4_END_INSTR(StrictNotEqualNumber, binaryop)
1955 QML_V4_BEGIN_INSTR(GtString, binaryop)
1957 const QString &a = *registers[instr->binaryop.left].getstringptr();
1958 const QString &b = *registers[instr->binaryop.right].getstringptr();
1959 bool result = a > b;
1960 if (instr->binaryop.left == instr->binaryop.output) {
1961 registers[instr->binaryop.output].cleanupString();
1962 MARK_CLEAN_REGISTER(instr->binaryop.output);
1964 registers[instr->binaryop.output].setbool(result);
1966 QML_V4_END_INSTR(GtString, binaryop)
1968 QML_V4_BEGIN_INSTR(LtString, binaryop)
1970 const QString &a = *registers[instr->binaryop.left].getstringptr();
1971 const QString &b = *registers[instr->binaryop.right].getstringptr();
1972 bool result = a < b;
1973 if (instr->binaryop.left == instr->binaryop.output) {
1974 registers[instr->binaryop.output].cleanupString();
1975 MARK_CLEAN_REGISTER(instr->binaryop.output);
1977 registers[instr->binaryop.output].setbool(result);
1979 QML_V4_END_INSTR(LtString, binaryop)
1981 QML_V4_BEGIN_INSTR(GeString, binaryop)
1983 const QString &a = *registers[instr->binaryop.left].getstringptr();
1984 const QString &b = *registers[instr->binaryop.right].getstringptr();
1985 bool result = a >= b;
1986 if (instr->binaryop.left == instr->binaryop.output) {
1987 registers[instr->binaryop.output].cleanupString();
1988 MARK_CLEAN_REGISTER(instr->binaryop.output);
1990 registers[instr->binaryop.output].setbool(result);
1992 QML_V4_END_INSTR(GeString, binaryop)
1994 QML_V4_BEGIN_INSTR(LeString, binaryop)
1996 const QString &a = *registers[instr->binaryop.left].getstringptr();
1997 const QString &b = *registers[instr->binaryop.right].getstringptr();
1998 bool result = a <= b;
1999 if (instr->binaryop.left == instr->binaryop.output) {
2000 registers[instr->binaryop.output].cleanupString();
2001 MARK_CLEAN_REGISTER(instr->binaryop.output);
2003 registers[instr->binaryop.output].setbool(result);
2005 QML_V4_END_INSTR(LeString, binaryop)
2007 QML_V4_BEGIN_INSTR(EqualString, binaryop)
2009 const QString &a = *registers[instr->binaryop.left].getstringptr();
2010 const QString &b = *registers[instr->binaryop.right].getstringptr();
2011 bool result = a == b;
2012 if (instr->binaryop.left == instr->binaryop.output) {
2013 registers[instr->binaryop.output].cleanupString();
2014 MARK_CLEAN_REGISTER(instr->binaryop.output);
2016 registers[instr->binaryop.output].setbool(result);
2018 QML_V4_END_INSTR(EqualString, binaryop)
2020 QML_V4_BEGIN_INSTR(NotEqualString, binaryop)
2022 const QString &a = *registers[instr->binaryop.left].getstringptr();
2023 const QString &b = *registers[instr->binaryop.right].getstringptr();
2024 bool result = a != b;
2025 if (instr->binaryop.left == instr->binaryop.output) {
2026 registers[instr->binaryop.output].cleanupString();
2027 MARK_CLEAN_REGISTER(instr->binaryop.output);
2029 registers[instr->binaryop.output].setbool(result);
2031 QML_V4_END_INSTR(NotEqualString, binaryop)
2033 QML_V4_BEGIN_INSTR(StrictEqualString, binaryop)
2035 const QString &a = *registers[instr->binaryop.left].getstringptr();
2036 const QString &b = *registers[instr->binaryop.right].getstringptr();
2037 bool result = a == b;
2038 if (instr->binaryop.left == instr->binaryop.output) {
2039 registers[instr->binaryop.output].cleanupString();
2040 MARK_CLEAN_REGISTER(instr->binaryop.output);
2042 registers[instr->binaryop.output].setbool(result);
2044 QML_V4_END_INSTR(StrictEqualString, binaryop)
2046 QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop)
2048 const QString &a = *registers[instr->binaryop.left].getstringptr();
2049 const QString &b = *registers[instr->binaryop.right].getstringptr();
2050 bool result = a != b;
2051 if (instr->binaryop.left == instr->binaryop.output) {
2052 registers[instr->binaryop.output].cleanupString();
2053 MARK_CLEAN_REGISTER(instr->binaryop.output);
2055 registers[instr->binaryop.output].setbool(result);
2057 QML_V4_END_INSTR(StrictNotEqualString, binaryop)
2059 QML_V4_BEGIN_INSTR(EqualObject, binaryop)
2061 const Register &left = registers[instr->binaryop.left];
2062 const Register &right = registers[instr->binaryop.right];
2063 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
2064 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
2065 registers[instr->binaryop.output].setbool(leftobj == rightobj);
2067 QML_V4_END_INSTR(EqualObject, binaryop)
2069 QML_V4_BEGIN_INSTR(NotEqualObject, binaryop)
2071 const Register &left = registers[instr->binaryop.left];
2072 const Register &right = registers[instr->binaryop.right];
2073 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
2074 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
2075 registers[instr->binaryop.output].setbool(leftobj != rightobj);
2077 QML_V4_END_INSTR(NotEqualObject, binaryop)
2079 QML_V4_BEGIN_INSTR(StrictEqualObject, binaryop)
2081 const Register &left = registers[instr->binaryop.left];
2082 const Register &right = registers[instr->binaryop.right];
2083 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
2084 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
2085 registers[instr->binaryop.output].setbool(leftobj == rightobj);
2087 QML_V4_END_INSTR(StrictEqualObject, binaryop)
2089 QML_V4_BEGIN_INSTR(StrictNotEqualObject, binaryop)
2091 const Register &left = registers[instr->binaryop.left];
2092 const Register &right = registers[instr->binaryop.right];
2093 QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject();
2094 QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject();
2095 registers[instr->binaryop.output].setbool(leftobj != rightobj);
2097 QML_V4_END_INSTR(StrictNotEqualObject, binaryop)
2099 QML_V4_BEGIN_INSTR(MathMaxNumber, binaryop)
2101 const Register &left = registers[instr->binaryop.left];
2102 const Register &right = registers[instr->binaryop.right];
2103 Register &output = registers[instr->binaryop.output];
2104 if (left.isUndefined() || right.isUndefined()) output.setUndefined();
2105 else output.setnumber(qMax(left.getnumber(), right.getnumber()));
2107 QML_V4_END_INSTR(MathMaxNumber, binaryop)
2109 QML_V4_BEGIN_INSTR(MathMinNumber, binaryop)
2111 const Register &left = registers[instr->binaryop.left];
2112 const Register &right = registers[instr->binaryop.right];
2113 Register &output = registers[instr->binaryop.output];
2114 if (left.isUndefined() || right.isUndefined()) output.setUndefined();
2115 else output.setnumber(qMin(left.getnumber(), right.getnumber()));
2117 QML_V4_END_INSTR(MathMinNumber, binaryop)
2119 QML_V4_BEGIN_INSTR(NewString, construct)
2121 Register &output = registers[instr->construct.reg];
2122 new (output.getstringptr()) QString;
2123 STRING_REGISTER(instr->construct.reg);
2125 QML_V4_END_INSTR(NewString, construct)
2127 QML_V4_BEGIN_INSTR(NewUrl, construct)
2129 Register &output = registers[instr->construct.reg];
2130 new (output.geturlptr()) QUrl;
2131 URL_REGISTER(instr->construct.reg);
2133 QML_V4_END_INSTR(NewUrl, construct)
2135 QML_V4_BEGIN_INSTR(Fetch, fetch)
2137 Register ® = registers[instr->fetch.reg];
2139 if (reg.isUndefined())
2140 THROW_EXCEPTION(instr->fetch.exceptionId);
2142 QObject *object = reg.getQObject();
2144 THROW_EXCEPTION(instr->fetch.exceptionId);
2146 INVALIDATION_CHECK(invalidated, object, instr->fetch.index);
2148 const Register::Type valueType = (Register::Type)instr->fetch.valueType;
2149 reg.init(valueType);
2150 if (instr->fetch.valueType >= FirstCleanupType)
2151 MARK_REGISTER(instr->fetch.reg);
2152 void *argv[] = { reg.typeDataPtr(), 0 };
2153 QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
2154 if (valueType == FloatType) {
2156 const double v = reg.getfloat();
2161 QML_V4_END_INSTR(Fetch, fetch)
2163 QML_V4_BEGIN_INSTR(TestV4Store, storetest)
2165 Register &data = registers[instr->storetest.reg];
2166 testBindingResult(*testBindingSource, bindingLine, bindingColumn, context,
2167 scope, data, instr->storetest.regType);
2169 QML_V4_END_INSTR(TestV4Store, storetest)
2171 QML_V4_BEGIN_INSTR(Store, store)
2173 Register &data = registers[instr->store.reg];
2175 if (data.isUndefined())
2176 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
2178 if (data.gettype() == QObjectStarType) {
2179 if (QObject *dataObject = data.getQObject()) {
2180 QQmlMetaObject dataMo(dataObject);
2182 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
2184 QQmlMetaObject receiverMo;
2186 if (QQmlData::get(output, false) && QQmlData::get(output, false)->propertyCache) {
2187 QQmlPropertyData *receiver =
2188 QQmlData::get(output, false)->propertyCache->property(instr->store.index);
2189 receiverMo = ep->rawMetaObjectForType(receiver->propType);
2191 QMetaProperty receiver = output->metaObject()->property(instr->store.index);
2192 receiverMo = ep->rawMetaObjectForType(receiver.userType());
2195 // Verify that these types are compatible
2196 if (!QQmlMetaObject::canConvert(dataMo, receiverMo)) {
2197 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") +
2198 QLatin1String(dataMo.className()) +
2199 QLatin1String(" to ") +
2200 QLatin1String(receiverMo.className()));
2205 if (instr->store.valueType == FloatType) {
2206 // cast numbers to floats
2207 const float v = (float) data.getnumber();
2211 if (data.gettype() == V8HandleType) {
2212 // This property must be a VME var property
2213 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(output);
2215 vmemo->setVMEProperty(instr->store.index, *data.gethandleptr());
2218 void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
2219 QMetaObject::metacall(output, QMetaObject::WriteProperty,
2220 instr->store.index, argv);
2225 QML_V4_END_INSTR(Store, store)
2227 QML_V4_BEGIN_INSTR(Copy, copy)
2228 registers[instr->copy.reg].copy(registers[instr->copy.src]);
2229 if (registers[instr->copy.reg].gettype() >= FirstCleanupType)
2230 MARK_REGISTER(instr->copy.reg);
2231 QML_V4_END_INSTR(Copy, copy)
2233 QML_V4_BEGIN_INSTR(Jump, jump)
2234 if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool())
2235 code += instr->jump.count;
2236 QML_V4_END_INSTR(Jump, jump)
2238 QML_V4_BEGIN_INSTR(BranchTrue, branchop)
2239 if (registers[instr->branchop.reg].getbool())
2240 code += instr->branchop.offset;
2241 QML_V4_END_INSTR(BranchTrue, branchop)
2243 QML_V4_BEGIN_INSTR(BranchFalse, branchop)
2244 if (! registers[instr->branchop.reg].getbool())
2245 code += instr->branchop.offset;
2246 QML_V4_END_INSTR(BranchFalse, branchop)
2248 QML_V4_BEGIN_INSTR(Branch, branchop)
2249 code += instr->branchop.offset;
2250 QML_V4_END_INSTR(Branch, branchop)
2252 QML_V4_BEGIN_INSTR(Block, blockop)
2253 executedBlocks |= instr->blockop.block;
2254 QML_V4_END_INSTR(Block, blockop)
2256 QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
2257 registers[instr->cleanup.reg].cleanup();
2258 QML_V4_END_INSTR(CleanupRegister, cleanup)
2260 QML_V4_BEGIN_INSTR(Throw, throwop)
2261 THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr());
2262 QML_V4_END_INSTR(Throw, throwop)
2264 #ifdef QML_THREADED_INTERPRETER
2268 qFatal("QV4: Unknown instruction %d encountered.", instr->common.type);
2275 Q_ASSERT(!"Unreachable code reached");
2279 delete testBindingSource;
2282 while (cleanupRegisterMask) {
2283 if (cleanupRegisterMask & 0x1)
2284 registers[reg].cleanup();
2287 cleanupRegisterMask >>= 1;