1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** 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/qdeclarativeaccessors_p.h>
50 #include <private/qdeclarativedebugtrace_p.h>
51 #include <private/qdeclarativemetatype_p.h>
52 #include <private/qdeclarativetrace_p.h>
54 #include <QtDeclarative/qdeclarativeinfo.h>
55 #include <QtCore/qnumeric.h>
56 #include <QtCore/qmath.h>
57 #include <math.h> // ::fmod
61 using namespace QDeclarativeJS;
65 typedef QDeclarativeRegisterType Type;
67 void setUndefined() { dataType = UndefinedType; }
68 void setNaN() { setqreal(qSNaN()); }
69 bool isUndefined() const { return dataType == UndefinedType; }
71 void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
72 QObject *getQObject() const { return qobjectValue; }
74 void setqreal(qreal v) { qrealValue = v; dataType = QRealType; }
75 qreal getqreal() const { return qrealValue; }
76 qreal &getqrealref() { return qrealValue; }
78 void setint(int v) { intValue = v; dataType = IntType; }
79 int getint() const { return intValue; }
80 int &getintref() { return intValue; }
82 void setbool(bool v) { boolValue = v; dataType = BoolType; }
83 bool getbool() const { return boolValue; }
84 bool &getboolref() { return boolValue; }
86 QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
87 QString *getstringptr() { return (QString *)typeDataPtr(); }
88 QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
89 const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
90 const QString *getstringptr() const { return (QString *)typeDataPtr(); }
91 const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
93 void *typeDataPtr() { return (void *)&data; }
94 void *typeMemory() { return (void *)data; }
95 const void *typeDataPtr() const { return (void *)&data; }
96 const void *typeMemory() const { return (void *)data; }
98 Type gettype() const { return dataType; }
99 void settype(Type t) { dataType = t; }
101 Type dataType; // Type of data
103 QObject *qobjectValue;
107 void *data[sizeof(QVariant)];
108 qint64 q_for_alignment_1;
109 double q_for_alignment_2;
112 inline void cleanup();
113 inline void cleanupString();
114 inline void cleanupUrl();
115 inline void cleanupVariant();
117 inline void copy(const Register &other);
118 inline void init(Type type);
119 #ifdef REGISTER_CLEANUP_DEBUG
125 if (dataType >= FirstCleanupType)
126 qWarning("Register leaked of type %d", dataType);
131 void Register::cleanup()
133 if (dataType >= FirstCleanupType) {
134 if (dataType == QStringType) {
135 getstringptr()->~QString();
136 } else if (dataType == QUrlType) {
137 geturlptr()->~QUrl();
138 } else if (dataType == QVariantType) {
139 getvariantptr()->~QVariant();
145 void Register::cleanupString()
147 getstringptr()->~QString();
151 void Register::cleanupUrl()
153 geturlptr()->~QUrl();
157 void Register::cleanupVariant()
159 getvariantptr()->~QVariant();
163 void Register::copy(const Register &other)
166 if (other.dataType >= FirstCleanupType) {
167 if (other.dataType == QStringType)
168 new (getstringptr()) QString(*other.getstringptr());
169 else if (other.dataType == QUrlType)
170 new (geturlptr()) QUrl(*other.geturlptr());
171 else if (other.dataType == QVariantType)
172 new (getvariantptr()) QVariant(*other.getvariantptr());
176 void Register::init(Type type)
179 if (dataType >= FirstCleanupType) {
180 if (dataType == QStringType)
181 new (getstringptr()) QString();
182 else if (dataType == QUrlType)
183 new (geturlptr()) QUrl();
184 else if (dataType == QVariantType)
185 new (getvariantptr()) QVariant();
189 } // end of anonymous namespace
191 QV4Bindings::QV4Bindings(const char *programData,
192 QDeclarativeContextData *context,
193 QDeclarativeRefCount *ref)
194 : subscriptions(0), program(0), dataRef(0), bindings(0)
196 program = (QV4Program *)programData;
198 if (dataRef) dataRef->addref();
201 subscriptions = new Subscription[program->subscriptions];
202 bindings = new Binding[program->bindings];
204 QDeclarativeAbstractExpression::setContext(context);
208 QV4Bindings::~QV4Bindings()
211 delete [] subscriptions; subscriptions = 0;
212 if (dataRef) dataRef->release();
215 QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *target,
216 QObject *scope, int property,
217 int line, int column)
219 Binding *rv = bindings + index;
222 rv->property = property;
229 addref(); // This is decremented in Binding::destroy()
234 void QV4Bindings::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
239 if (e) update(flags);
243 void QV4Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
245 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding);
246 if (parent->context())
247 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Binding,
248 parent->context()->url, line, column);
249 parent->run(this, flags);
250 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding);
253 void QV4Bindings::Binding::destroy()
262 void QV4Bindings::Subscription::subscriptionCallback(QDeclarativeNotifierEndpoint *e)
264 Subscription *s = static_cast<Subscription *>(e);
265 s->bindings->subscriptionNotify(s->method);
268 void QV4Bindings::subscriptionNotify(int id)
270 QV4Program::BindingReferenceList *list = program->signalTable(id);
272 for (quint32 ii = 0; ii < list->count; ++ii) {
273 QV4Program::BindingReference *bindingRef = list->bindings + ii;
275 Binding *binding = bindings + bindingRef->binding;
277 if (binding->executedBlocks & bindingRef->blockMask) {
278 run(binding, QDeclarativePropertyPrivate::DontRemoveBinding);
283 void QV4Bindings::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
285 if (!binding->enabled)
288 QDeclarativeContextData *context = QDeclarativeAbstractExpression::context();
289 if (!context || !context->isValid())
292 QDeclarativeTrace trace("V4 Binding Update");
293 trace.addDetail("URL", context->url);
294 trace.addDetail("Line", binding->line);
295 trace.addDetail("Column", binding->column);
297 if (binding->updating) {
299 if (binding->property & 0xFFFF0000) {
300 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
302 QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
305 name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
306 name.append(QLatin1String("."));
307 name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
309 name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
311 qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name);
315 binding->updating = true;
316 if (binding->property & 0xFFFF0000) {
317 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
319 QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
321 vt->read(binding->target, binding->property & 0xFFFF);
323 QObject *target = vt;
324 run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags);
326 vt->write(binding->target, binding->property & 0xFFFF, flags);
328 run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags);
330 binding->updating = false;
334 void QV4Bindings::unsubscribe(int subIndex)
336 Subscription *sub = (subscriptions + subIndex);
340 void QV4Bindings::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex)
342 unsubscribe(subIndex);
344 if (p->idValues[idIndex]) {
345 Subscription *sub = (subscriptions + subIndex);
346 sub->bindings = this;
347 sub->method = subIndex;
348 sub->connect(&p->idValues[idIndex].bindings);
352 void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
354 Subscription *sub = (subscriptions + subIndex);
355 if (sub->isConnected(o, notifyIndex))
357 sub->bindings = this;
358 sub->method = subIndex;
360 sub->connect(o, notifyIndex);
365 // Conversion functions - these MUST match the QtScript expression path
366 inline static qreal toReal(Register *reg, int type, bool *ok = 0)
370 if (type == QMetaType::QReal) {
371 return reg->getqreal();
372 } else if (type == qMetaTypeId<QVariant>()) {
373 return reg->getvariantptr()->toReal();
380 inline static QString toString(Register *reg, int type, bool *ok = 0)
384 if (type == QMetaType::QReal) {
385 return QString::number(reg->getqreal());
386 } else if (type == QMetaType::Int) {
387 return QString::number(reg->getint());
388 } else if (type == qMetaTypeId<QVariant>()) {
389 return reg->getvariantptr()->toString();
390 } else if (type == QMetaType::QString) {
391 return *reg->getstringptr();
398 inline static bool toBool(Register *reg, int type, bool *ok = 0)
402 if (type == QMetaType::Bool) {
403 return reg->getbool();
404 } else if (type == qMetaTypeId<QVariant>()) {
405 return reg->getvariantptr()->toBool();
412 inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0)
417 if (type == qMetaTypeId<QVariant>()) {
418 QVariant *var = reg->getvariantptr();
419 int vt = var->type();
420 if (vt == QVariant::Url) {
422 } else if (vt == QVariant::ByteArray) {
423 // Preserve any valid percent-encoded octets supplied by the source
424 base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode);
425 } else if (vt == QVariant::String) {
426 base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode);
431 } else if (type == QMetaType::QString) {
432 base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode);
438 if (!base.isEmpty() && base.isRelative())
439 return context->url.resolved(base);
444 static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
446 QVariant qtscript = qtscriptRaw;
448 if (qtscript.userType() == v4.userType()) {
449 } else if (qtscript.canConvert((QVariant::Type)v4.userType())) {
450 qtscript.convert((QVariant::Type)v4.userType());
451 } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) {
452 qtscript = qVariantFromValue<QObject *>(0);
457 int type = qtscript.userType();
459 if (type == qMetaTypeId<QDeclarative1AnchorLine>()) {
460 QDeclarative1AnchorLine la = qvariant_cast<QDeclarative1AnchorLine>(qtscript);
461 QDeclarative1AnchorLine ra = qvariant_cast<QDeclarative1AnchorLine>(v4);
464 } else if (type == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
465 return QDeclarativeMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData());
466 } else if (type == QMetaType::Double) {
468 double la = qvariant_cast<double>(qtscript);
469 double lr = qvariant_cast<double>(v4);
471 return la == lr || (qIsNaN(la) && qIsNaN(lr));
473 } else if (type == QMetaType::Float) {
475 float la = qvariant_cast<float>(qtscript);
476 float lr = qvariant_cast<float>(v4);
478 return la == lr || (qIsNaN(la) && qIsNaN(lr));
481 return qtscript == v4;
485 QByteArray testResultToString(const QVariant &result, bool undefined)
497 static void testBindingResult(const QString &binding, int line, int column,
498 QDeclarativeContextData *context, QObject *scope,
499 const Register &result, int resultType)
501 QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding);
502 bool isUndefined = false;
503 QVariant value = expression.evaluate(&isUndefined);
505 bool iserror = false;
506 QByteArray qtscriptResult;
509 if (expression.hasError()) {
511 qtscriptResult = "exception";
513 qtscriptResult = testResultToString(value, isUndefined);
516 if (isUndefined && result.isUndefined()) {
518 } else if(isUndefined != result.isUndefined()) {
523 if (!result.isUndefined()) {
524 switch (resultType) {
525 case QMetaType::QString:
526 v4value = *result.getstringptr();
528 case QMetaType::QUrl:
529 v4value = *result.geturlptr();
531 case QMetaType::QObjectStar:
532 v4value = qVariantFromValue<QObject *>(result.getQObject());
534 case QMetaType::Bool:
535 v4value = result.getbool();
538 v4value = result.getint();
540 case QMetaType::QReal:
541 v4value = result.getqreal();
544 if (resultType == qMetaTypeId<QDeclarative1AnchorLine>()) {
545 v4value = qVariantFromValue<QDeclarative1AnchorLine>(*(QDeclarative1AnchorLine *)result.typeDataPtr());
546 } else if (resultType == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
547 v4value = QVariant(QDeclarativeMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
550 v4Result = "Unknown V4 type";
554 if (v4Result.isEmpty())
555 v4Result = testResultToString(v4value, result.isUndefined());
557 if (!testCompareVariants(value, v4value))
561 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
563 qWarning().nospace() << " Binding: " << binding;
564 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
565 qWarning().nospace() << " V4: " << v4Result.constData();
569 static void testBindingException(const QString &binding, int line, int column,
570 QDeclarativeContextData *context, QObject *scope)
572 QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding);
573 bool isUndefined = false;
574 QVariant value = expression.evaluate(&isUndefined);
576 if (!expression.hasError()) {
577 QByteArray qtscriptResult = testResultToString(value, isUndefined);
578 qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
579 qWarning().nospace() << " Binding: " << binding;
580 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
581 qWarning().nospace() << " V4: exception";
585 static void throwException(int id, QDeclarativeDelayedError *error,
586 QV4Program *program, QDeclarativeContextData *context,
587 const QString &description = QString())
589 error->error.setUrl(context->url);
590 if (description.isEmpty())
591 error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
593 error->error.setDescription(description);
595 quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id);
596 error->error.setLine((e >> 32) & 0xFFFFFFFF);
597 error->error.setColumn(e & 0xFFFFFFFF);
599 error->error.setLine(-1);
600 error->error.setColumn(-1);
602 if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine)))
603 QDeclarativeEnginePrivate::warning(context->engine, error->error);
606 const qreal QV4Bindings::D32 = 4294967296.0;
608 qint32 QV4Bindings::toInt32(qreal n)
610 if (qIsNaN(n) || qIsInf(n) || (n == 0))
613 double sign = (n < 0) ? -1.0 : 1.0;
614 qreal abs_n = fabs(n);
616 n = ::fmod(sign * ::floor(abs_n), D32);
617 const double D31 = D32 / 2.0;
619 if (sign == -1 && n < -D31)
622 else if (sign != -1 && n >= D31)
628 inline quint32 QV4Bindings::toUint32(qreal n)
630 if (qIsNaN(n) || qIsInf(n) || (n == 0))
633 double sign = (n < 0) ? -1.0 : 1.0;
634 qreal abs_n = fabs(n);
636 n = ::fmod(sign * ::floor(abs_n), D32);
644 #define THROW_EXCEPTION_STR(id, str) { \
645 if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \
646 throwException((id), error, program, context, (str)); \
647 goto exceptionExit; \
650 #define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
652 #define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
653 #define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg))
655 #define STRING_REGISTER(reg) { \
656 registers[(reg)].settype(QStringType); \
657 MARK_REGISTER(reg); \
660 #define URL_REGISTER(reg) { \
661 registers[(reg)].settype(QUrlType); \
662 MARK_REGISTER(reg); \
665 #define VARIANT_REGISTER(reg) { \
666 registers[(reg)].settype(QVariantType); \
667 MARK_REGISTER(reg); \
670 #ifdef QML_THREADED_INTERPRETER
671 void **QV4Bindings::getDecodeInstrTable()
673 static void **decode_instr;
675 QV4Bindings *dummy = new QV4Bindings(0, 0, 0);
676 quint32 executedBlocks = 0;
677 dummy->run(0, executedBlocks, 0, 0, 0, 0,
678 QDeclarativePropertyPrivate::BypassInterceptor,
686 void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
687 QDeclarativeContextData *context, QDeclarativeDelayedError *error,
688 QObject *scope, QObject *output,
689 QDeclarativePropertyPrivate::WriteFlags storeFlags
690 #ifdef QML_THREADED_INTERPRETER
695 #ifdef QML_THREADED_INTERPRETER
697 static void *decode_instr[] = {
698 FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR)
701 *table = decode_instr;
707 error->removeError();
709 Register registers[32];
710 quint32 cleanupRegisterMask = 0;
714 const char *code = program->instructions();
715 code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
716 const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
718 const char *data = program->data();
720 QString *testBindingSource = 0;
721 bool testBinding = false;
723 int bindingColumn = 0;
725 #ifdef QML_THREADED_INTERPRETER
726 goto *instr->common.code;
729 switch (instr->common.type) {
732 QML_V4_BEGIN_INSTR(Noop, common)
733 QML_V4_END_INSTR(Noop, common)
735 QML_V4_BEGIN_INSTR(BindingId, id)
736 bindingLine = instr->id.line;
737 bindingColumn = instr->id.column;
738 QML_V4_END_INSTR(BindingId, id)
740 QML_V4_BEGIN_INSTR(SubscribeId, subscribeop)
741 subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset);
742 QML_V4_END_INSTR(SubscribeId, subscribeop)
744 QML_V4_BEGIN_INSTR(Subscribe, subscribeop)
747 const Register &object = registers[instr->subscribeop.reg];
748 if (!object.isUndefined()) o = object.getQObject();
749 subscribe(o, instr->subscribeop.index, instr->subscribeop.offset);
751 QML_V4_END_INSTR(Subscribe, subscribeop)
753 QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe)
755 Register ® = registers[instr->fetchAndSubscribe.reg];
757 if (reg.isUndefined())
758 THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
760 QObject *object = reg.getQObject();
764 int subIdx = instr->fetchAndSubscribe.subscription;
765 Subscription *sub = 0;
767 sub = (subscriptions + subIdx);
768 sub->bindings = this;
769 sub->method = subIdx;
771 reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
772 if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
773 MARK_REGISTER(instr->fetchAndSubscribe.reg);
774 QDeclarativeAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
775 accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
778 if (accessors->notifier) {
779 QDeclarativeNotifier *notifier = 0;
780 accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier);
781 if (notifier) sub->connect(notifier);
782 } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
783 sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex);
787 QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
789 QML_V4_BEGIN_INSTR(LoadId, load)
790 registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
791 QML_V4_END_INSTR(LoadId, load)
793 QML_V4_BEGIN_INSTR(LoadScope, load)
794 registers[instr->load.reg].setQObject(scope);
795 QML_V4_END_INSTR(LoadScope, load)
797 QML_V4_BEGIN_INSTR(LoadRoot, load)
798 registers[instr->load.reg].setQObject(context->contextObject);
799 QML_V4_END_INSTR(LoadRoot, load)
801 QML_V4_BEGIN_INSTR(LoadAttached, attached)
803 const Register &input = registers[instr->attached.reg];
804 Register &output = registers[instr->attached.output];
805 if (input.isUndefined())
806 THROW_EXCEPTION(instr->attached.exceptionId);
808 QObject *object = registers[instr->attached.reg].getQObject();
810 output.setUndefined();
812 QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true);
814 output.setQObject(attached);
817 QML_V4_END_INSTR(LoadAttached, attached)
819 QML_V4_BEGIN_INSTR(UnaryNot, unaryop)
821 registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool());
823 QML_V4_END_INSTR(UnaryNot, unaryop)
825 QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop)
827 registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal());
829 QML_V4_END_INSTR(UnaryMinusReal, unaryop)
831 QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
833 registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint());
835 QML_V4_END_INSTR(UnaryMinusInt, unaryop)
837 QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop)
839 registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal());
841 QML_V4_END_INSTR(UnaryPlusReal, unaryop)
843 QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
845 registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint());
847 QML_V4_END_INSTR(UnaryPlusInt, unaryop)
849 QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop)
851 const Register &src = registers[instr->unaryop.src];
852 Register &output = registers[instr->unaryop.output];
853 if (src.isUndefined()) output.setUndefined();
854 else output.setint(src.getbool());
856 QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
858 QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop)
860 const Register &src = registers[instr->unaryop.src];
861 Register &output = registers[instr->unaryop.output];
862 if (src.isUndefined()) output.setUndefined();
863 else output.setqreal(src.getbool());
865 QML_V4_END_INSTR(ConvertBoolToReal, unaryop)
867 QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
869 const Register &src = registers[instr->unaryop.src];
870 Register &output = registers[instr->unaryop.output];
871 if (src.isUndefined()) {
872 output.setUndefined();
874 new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false"));
875 STRING_REGISTER(instr->unaryop.output);
878 QML_V4_END_INSTR(ConvertBoolToString, unaryop)
880 QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
882 const Register &src = registers[instr->unaryop.src];
883 Register &output = registers[instr->unaryop.output];
884 if (src.isUndefined()) output.setUndefined();
885 else output.setbool(src.getint());
887 QML_V4_END_INSTR(ConvertIntToBool, unaryop)
889 QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop)
891 const Register &src = registers[instr->unaryop.src];
892 Register &output = registers[instr->unaryop.output];
893 if (src.isUndefined()) output.setUndefined();
894 else output.setqreal(qreal(src.getint()));
896 QML_V4_END_INSTR(ConvertIntToReal, unaryop)
898 QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
900 const Register &src = registers[instr->unaryop.src];
901 Register &output = registers[instr->unaryop.output];
902 if (src.isUndefined()) {
903 output.setUndefined();
905 new (output.getstringptr()) QString(QString::number(src.getint()));
906 STRING_REGISTER(instr->unaryop.output);
909 QML_V4_END_INSTR(ConvertIntToString, unaryop)
911 QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop)
913 const Register &src = registers[instr->unaryop.src];
914 Register &output = registers[instr->unaryop.output];
915 if (src.isUndefined()) output.setUndefined();
916 else output.setbool(src.getqreal() != 0);
918 QML_V4_END_INSTR(ConvertRealToBool, unaryop)
920 QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop)
922 const Register &src = registers[instr->unaryop.src];
923 Register &output = registers[instr->unaryop.output];
924 if (src.isUndefined()) output.setUndefined();
925 else output.setint(toInt32(src.getqreal()));
927 QML_V4_END_INSTR(ConvertRealToInt, unaryop)
929 QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop)
931 const Register &src = registers[instr->unaryop.src];
932 Register &output = registers[instr->unaryop.output];
934 if (src.isUndefined()) {
935 output.setUndefined();
937 new (output.getstringptr()) QString(QString::number(src.getqreal()));
938 STRING_REGISTER(instr->unaryop.output);
941 QML_V4_END_INSTR(ConvertRealToString, unaryop)
943 QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
945 const Register &src = registers[instr->unaryop.src];
946 Register &output = registers[instr->unaryop.output];
948 if (src.isUndefined()) {
949 output.setUndefined();
951 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
952 // Ideally we should just call the methods in the QScript namespace directly.
953 QJSValue tmp(*src.getstringptr());
954 if (instr->unaryop.src == instr->unaryop.output) {
955 output.cleanupString();
956 MARK_CLEAN_REGISTER(instr->unaryop.output);
958 output.setbool(tmp.toBool());
961 QML_V4_END_INSTR(ConvertStringToBool, unaryop)
963 QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop)
965 const Register &src = registers[instr->unaryop.src];
966 Register &output = registers[instr->unaryop.output];
968 if (src.isUndefined()) {
969 output.setUndefined();
971 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
972 // Ideally we should just call the methods in the QScript namespace directly.
973 QJSValue tmp(*src.getstringptr());
974 if (instr->unaryop.src == instr->unaryop.output) {
975 output.cleanupString();
976 MARK_CLEAN_REGISTER(instr->unaryop.output);
978 output.setint(tmp.toInt());
981 QML_V4_END_INSTR(ConvertStringToInt, unaryop)
983 QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop)
985 const Register &src = registers[instr->unaryop.src];
986 Register &output = registers[instr->unaryop.output];
988 if (src.isUndefined()) {
989 output.setUndefined();
991 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
992 // Ideally we should just call the methods in the QScript namespace directly.
993 QJSValue tmp(*src.getstringptr());
994 if (instr->unaryop.src == instr->unaryop.output) {
995 output.cleanupString();
996 MARK_CLEAN_REGISTER(instr->unaryop.output);
998 output.setqreal(tmp.toNumber());
1001 QML_V4_END_INSTR(ConvertStringToReal, unaryop)
1003 QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
1005 const Register &src = registers[instr->unaryop.src];
1006 Register &output = registers[instr->unaryop.output];
1008 if (src.isUndefined()) {
1009 output.setUndefined();
1011 const QString tmp(*src.getstringptr());
1012 if (instr->unaryop.src == instr->unaryop.output) {
1013 output.cleanupString();
1014 MARK_CLEAN_REGISTER(instr->unaryop.output);
1016 QUrl *urlPtr = output.geturlptr();
1017 new (urlPtr) QUrl();
1018 urlPtr->setEncodedUrl(tmp.toUtf8(), QUrl::TolerantMode);
1020 URL_REGISTER(instr->unaryop.output);
1023 QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
1025 QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
1027 const Register &src = registers[instr->unaryop.src];
1028 Register &output = registers[instr->unaryop.output];
1030 if (src.isUndefined()) {
1031 output.setUndefined();
1033 const QUrl tmp(*src.geturlptr());
1034 if (instr->unaryop.src == instr->unaryop.output) {
1035 output.cleanupUrl();
1036 MARK_CLEAN_REGISTER(instr->unaryop.output);
1038 output.setbool(!tmp.isEmpty());
1041 QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
1043 QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
1045 const Register &src = registers[instr->unaryop.src];
1046 Register &output = registers[instr->unaryop.output];
1048 if (src.isUndefined()) {
1049 output.setUndefined();
1051 const QUrl tmp(*src.geturlptr());
1052 if (instr->unaryop.src == instr->unaryop.output) {
1053 output.cleanupUrl();
1054 MARK_CLEAN_REGISTER(instr->unaryop.output);
1056 new (output.getstringptr()) QString(tmp.toString());
1057 STRING_REGISTER(instr->unaryop.output);
1060 QML_V4_END_INSTR(ConvertUrlToString, unaryop)
1062 QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
1064 const Register &src = registers[instr->unaryop.src];
1065 Register &output = registers[instr->unaryop.output];
1066 if (src.isUndefined()) {
1067 output.setUndefined();
1069 const QUrl tmp(*src.geturlptr());
1070 if (instr->unaryop.src == instr->unaryop.output) {
1071 *output.geturlptr() = context->resolvedUrl(tmp);
1073 new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
1074 URL_REGISTER(instr->unaryop.output);
1078 QML_V4_END_INSTR(ResolveUrl, unaryop)
1080 QML_V4_BEGIN_INSTR(MathSinReal, 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.setqreal(qSin(src.getqreal()));
1087 QML_V4_END_INSTR(MathSinReal, unaryop)
1089 QML_V4_BEGIN_INSTR(MathCosReal, unaryop)
1091 const Register &src = registers[instr->unaryop.src];
1092 Register &output = registers[instr->unaryop.output];
1093 if (src.isUndefined()) output.setUndefined();
1094 else output.setqreal(qCos(src.getqreal()));
1096 QML_V4_END_INSTR(MathCosReal, unaryop)
1098 QML_V4_BEGIN_INSTR(MathRoundReal, unaryop)
1100 const Register &src = registers[instr->unaryop.src];
1101 Register &output = registers[instr->unaryop.output];
1102 if (src.isUndefined()) output.setUndefined();
1103 else output.setint(qRound(src.getqreal()));
1105 QML_V4_END_INSTR(MathRoundReal, unaryop)
1107 QML_V4_BEGIN_INSTR(MathFloorReal, unaryop)
1109 const Register &src = registers[instr->unaryop.src];
1110 Register &output = registers[instr->unaryop.output];
1111 if (src.isUndefined()) output.setUndefined();
1112 else output.setint(qFloor(src.getqreal()));
1114 QML_V4_END_INSTR(MathFloorReal, unaryop)
1116 QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
1118 static const qreal qmlPI = 2.0 * qAsin(1.0);
1119 Register &output = registers[instr->unaryop.output];
1120 output.setqreal(qmlPI);
1122 QML_V4_END_INSTR(MathPIReal, unaryop)
1124 QML_V4_BEGIN_INSTR(LoadReal, real_value)
1125 registers[instr->real_value.reg].setqreal(instr->real_value.value);
1126 QML_V4_END_INSTR(LoadReal, real_value)
1128 QML_V4_BEGIN_INSTR(LoadInt, int_value)
1129 registers[instr->int_value.reg].setint(instr->int_value.value);
1130 QML_V4_END_INSTR(LoadInt, int_value)
1132 QML_V4_BEGIN_INSTR(LoadBool, bool_value)
1133 registers[instr->bool_value.reg].setbool(instr->bool_value.value);
1134 QML_V4_END_INSTR(LoadBool, bool_value)
1136 QML_V4_BEGIN_INSTR(LoadString, string_value)
1138 Register &output = registers[instr->string_value.reg];
1139 QChar *string = (QChar *)(data + instr->string_value.offset);
1140 new (output.getstringptr()) QString(string, instr->string_value.length);
1141 STRING_REGISTER(instr->string_value.reg);
1143 QML_V4_END_INSTR(LoadString, string_value)
1145 QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
1147 testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
1150 QML_V4_END_INSTR(String, string_value)
1152 QML_V4_BEGIN_INSTR(BitAndInt, binaryop)
1154 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() &
1155 registers[instr->binaryop.right].getint());
1157 QML_V4_END_INSTR(BitAndInt, binaryop)
1159 QML_V4_BEGIN_INSTR(BitOrInt, binaryop)
1161 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() |
1162 registers[instr->binaryop.right].getint());
1164 QML_V4_END_INSTR(BitAndInt, binaryop)
1166 QML_V4_BEGIN_INSTR(BitXorInt, binaryop)
1168 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^
1169 registers[instr->binaryop.right].getint());
1171 QML_V4_END_INSTR(BitXorInt, binaryop)
1173 QML_V4_BEGIN_INSTR(AddReal, binaryop)
1175 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() +
1176 registers[instr->binaryop.right].getqreal());
1178 QML_V4_END_INSTR(AddReal, binaryop)
1180 QML_V4_BEGIN_INSTR(AddString, binaryop)
1182 QString &string = *registers[instr->binaryop.output].getstringptr();
1183 if (instr->binaryop.output == instr->binaryop.left) {
1184 string += registers[instr->binaryop.right].getstringptr();
1186 string = *registers[instr->binaryop.left].getstringptr() +
1187 *registers[instr->binaryop.right].getstringptr();
1190 QML_V4_END_INSTR(AddString, binaryop)
1192 QML_V4_BEGIN_INSTR(SubReal, binaryop)
1194 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() -
1195 registers[instr->binaryop.right].getqreal());
1197 QML_V4_END_INSTR(SubReal, binaryop)
1199 QML_V4_BEGIN_INSTR(MulReal, binaryop)
1201 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() *
1202 registers[instr->binaryop.right].getqreal());
1204 QML_V4_END_INSTR(MulReal, binaryop)
1206 QML_V4_BEGIN_INSTR(DivReal, binaryop)
1208 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() /
1209 registers[instr->binaryop.right].getqreal());
1211 QML_V4_END_INSTR(DivReal, binaryop)
1213 QML_V4_BEGIN_INSTR(ModReal, binaryop)
1215 Register &target = registers[instr->binaryop.output];
1216 const Register &left = registers[instr->binaryop.left];
1217 const Register &right = registers[instr->binaryop.right];
1218 if (QMetaType::QReal == QMetaType::Float)
1219 target.setqreal(::fmodf(left.getqreal(), right.getqreal()));
1221 target.setqreal(::fmod(left.getqreal(), right.getqreal()));
1223 QML_V4_END_INSTR(ModInt, binaryop)
1225 QML_V4_BEGIN_INSTR(LShiftInt, binaryop)
1227 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() <<
1228 registers[instr->binaryop.right].getint());
1230 QML_V4_END_INSTR(LShiftInt, binaryop)
1232 QML_V4_BEGIN_INSTR(RShiftInt, binaryop)
1234 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >>
1235 registers[instr->binaryop.right].getint());
1237 QML_V4_END_INSTR(RShiftInt, binaryop)
1239 QML_V4_BEGIN_INSTR(URShiftInt, binaryop)
1241 registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >>
1242 registers[instr->binaryop.right].getint());
1244 QML_V4_END_INSTR(URShiftInt, binaryop)
1246 QML_V4_BEGIN_INSTR(GtReal, binaryop)
1248 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >
1249 registers[instr->binaryop.right].getqreal());
1251 QML_V4_END_INSTR(GtReal, binaryop)
1253 QML_V4_BEGIN_INSTR(LtReal, binaryop)
1255 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <
1256 registers[instr->binaryop.right].getqreal());
1258 QML_V4_END_INSTR(LtReal, binaryop)
1260 QML_V4_BEGIN_INSTR(GeReal, binaryop)
1262 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >=
1263 registers[instr->binaryop.right].getqreal());
1265 QML_V4_END_INSTR(GeReal, binaryop)
1267 QML_V4_BEGIN_INSTR(LeReal, binaryop)
1269 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <=
1270 registers[instr->binaryop.right].getqreal());
1272 QML_V4_END_INSTR(LeReal, binaryop)
1274 QML_V4_BEGIN_INSTR(EqualReal, binaryop)
1276 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
1277 registers[instr->binaryop.right].getqreal());
1279 QML_V4_END_INSTR(EqualReal, binaryop)
1281 QML_V4_BEGIN_INSTR(NotEqualReal, binaryop)
1283 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
1284 registers[instr->binaryop.right].getqreal());
1286 QML_V4_END_INSTR(NotEqualReal, binaryop)
1288 QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop)
1290 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
1291 registers[instr->binaryop.right].getqreal());
1293 QML_V4_END_INSTR(StrictEqualReal, binaryop)
1295 QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop)
1297 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
1298 registers[instr->binaryop.right].getqreal());
1300 QML_V4_END_INSTR(StrictNotEqualReal, binaryop)
1302 QML_V4_BEGIN_INSTR(GtString, binaryop)
1304 const QString &a = *registers[instr->binaryop.left].getstringptr();
1305 const QString &b = *registers[instr->binaryop.right].getstringptr();
1306 bool result = a > b;
1307 if (instr->binaryop.left == instr->binaryop.output) {
1308 registers[instr->binaryop.output].cleanupString();
1309 MARK_CLEAN_REGISTER(instr->binaryop.output);
1311 registers[instr->binaryop.output].setbool(result);
1313 QML_V4_END_INSTR(GtString, binaryop)
1315 QML_V4_BEGIN_INSTR(LtString, binaryop)
1317 const QString &a = *registers[instr->binaryop.left].getstringptr();
1318 const QString &b = *registers[instr->binaryop.right].getstringptr();
1319 bool result = a < b;
1320 if (instr->binaryop.left == instr->binaryop.output) {
1321 registers[instr->binaryop.output].cleanupString();
1322 MARK_CLEAN_REGISTER(instr->binaryop.output);
1324 registers[instr->binaryop.output].setbool(result);
1326 QML_V4_END_INSTR(LtString, binaryop)
1328 QML_V4_BEGIN_INSTR(GeString, binaryop)
1330 const QString &a = *registers[instr->binaryop.left].getstringptr();
1331 const QString &b = *registers[instr->binaryop.right].getstringptr();
1332 bool result = a >= b;
1333 if (instr->binaryop.left == instr->binaryop.output) {
1334 registers[instr->binaryop.output].cleanupString();
1335 MARK_CLEAN_REGISTER(instr->binaryop.output);
1337 registers[instr->binaryop.output].setbool(result);
1339 QML_V4_END_INSTR(GeString, binaryop)
1341 QML_V4_BEGIN_INSTR(LeString, binaryop)
1343 const QString &a = *registers[instr->binaryop.left].getstringptr();
1344 const QString &b = *registers[instr->binaryop.right].getstringptr();
1345 bool result = a <= b;
1346 if (instr->binaryop.left == instr->binaryop.output) {
1347 registers[instr->binaryop.output].cleanupString();
1348 MARK_CLEAN_REGISTER(instr->binaryop.output);
1350 registers[instr->binaryop.output].setbool(result);
1352 QML_V4_END_INSTR(LeString, binaryop)
1354 QML_V4_BEGIN_INSTR(EqualString, binaryop)
1356 const QString &a = *registers[instr->binaryop.left].getstringptr();
1357 const QString &b = *registers[instr->binaryop.right].getstringptr();
1358 bool result = a == b;
1359 if (instr->binaryop.left == instr->binaryop.output) {
1360 registers[instr->binaryop.output].cleanupString();
1361 MARK_CLEAN_REGISTER(instr->binaryop.output);
1363 registers[instr->binaryop.output].setbool(result);
1365 QML_V4_END_INSTR(EqualString, binaryop)
1367 QML_V4_BEGIN_INSTR(NotEqualString, binaryop)
1369 const QString &a = *registers[instr->binaryop.left].getstringptr();
1370 const QString &b = *registers[instr->binaryop.right].getstringptr();
1371 bool result = a != b;
1372 if (instr->binaryop.left == instr->binaryop.output) {
1373 registers[instr->binaryop.output].cleanupString();
1374 MARK_CLEAN_REGISTER(instr->binaryop.output);
1376 registers[instr->binaryop.output].setbool(result);
1378 QML_V4_END_INSTR(NotEqualString, binaryop)
1380 QML_V4_BEGIN_INSTR(StrictEqualString, binaryop)
1382 const QString &a = *registers[instr->binaryop.left].getstringptr();
1383 const QString &b = *registers[instr->binaryop.right].getstringptr();
1384 bool result = a == b;
1385 if (instr->binaryop.left == instr->binaryop.output) {
1386 registers[instr->binaryop.output].cleanupString();
1387 MARK_CLEAN_REGISTER(instr->binaryop.output);
1389 registers[instr->binaryop.output].setbool(result);
1391 QML_V4_END_INSTR(StrictEqualString, binaryop)
1393 QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop)
1395 const QString &a = *registers[instr->binaryop.left].getstringptr();
1396 const QString &b = *registers[instr->binaryop.right].getstringptr();
1397 bool result = a != b;
1398 if (instr->binaryop.left == instr->binaryop.output) {
1399 registers[instr->binaryop.output].cleanupString();
1400 MARK_CLEAN_REGISTER(instr->binaryop.output);
1402 registers[instr->binaryop.output].setbool(result);
1404 QML_V4_END_INSTR(StrictNotEqualString, binaryop)
1406 QML_V4_BEGIN_INSTR(NewString, construct)
1408 Register &output = registers[instr->construct.reg];
1409 new (output.getstringptr()) QString;
1410 STRING_REGISTER(instr->construct.reg);
1412 QML_V4_END_INSTR(NewString, construct)
1414 QML_V4_BEGIN_INSTR(NewUrl, construct)
1416 Register &output = registers[instr->construct.reg];
1417 new (output.geturlptr()) QUrl;
1418 URL_REGISTER(instr->construct.reg);
1420 QML_V4_END_INSTR(NewUrl, construct)
1422 QML_V4_BEGIN_INSTR(Fetch, fetch)
1424 Register ® = registers[instr->fetch.reg];
1426 if (reg.isUndefined())
1427 THROW_EXCEPTION(instr->fetch.exceptionId);
1429 QObject *object = reg.getQObject();
1431 THROW_EXCEPTION(instr->fetch.exceptionId);
1433 reg.init((Register::Type)instr->fetch.valueType);
1434 if (instr->fetch.valueType >= FirstCleanupType)
1435 MARK_REGISTER(instr->fetch.reg);
1436 void *argv[] = { reg.typeDataPtr(), 0 };
1437 QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
1440 QML_V4_END_INSTR(Fetch, fetch)
1442 QML_V4_BEGIN_INSTR(TestV4Store, storetest)
1444 Register &data = registers[instr->storetest.reg];
1445 testBindingResult(*testBindingSource, bindingLine, bindingColumn, context,
1446 scope, data, instr->storetest.regType);
1448 QML_V4_END_INSTR(TestV4Store, storetest)
1450 QML_V4_BEGIN_INSTR(Store, store)
1452 Register &data = registers[instr->store.reg];
1454 if (data.isUndefined())
1455 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
1458 void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
1459 QMetaObject::metacall(output, QMetaObject::WriteProperty,
1460 instr->store.index, argv);
1464 QML_V4_END_INSTR(Store, store)
1466 QML_V4_BEGIN_INSTR(Copy, copy)
1467 registers[instr->copy.reg].copy(registers[instr->copy.src]);
1468 if (registers[instr->copy.reg].gettype() >= FirstCleanupType)
1469 MARK_REGISTER(instr->copy.reg);
1470 QML_V4_END_INSTR(Copy, copy)
1472 QML_V4_BEGIN_INSTR(Jump, jump)
1473 if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool())
1474 code += instr->jump.count;
1475 QML_V4_END_INSTR(Jump, jump)
1477 QML_V4_BEGIN_INSTR(BranchTrue, branchop)
1478 if (registers[instr->branchop.reg].getbool())
1479 code += instr->branchop.offset;
1480 QML_V4_END_INSTR(BranchTrue, branchop)
1482 QML_V4_BEGIN_INSTR(BranchFalse, branchop)
1483 if (! registers[instr->branchop.reg].getbool())
1484 code += instr->branchop.offset;
1485 QML_V4_END_INSTR(BranchFalse, branchop)
1487 QML_V4_BEGIN_INSTR(Branch, branchop)
1488 code += instr->branchop.offset;
1489 QML_V4_END_INSTR(Branch, branchop)
1491 QML_V4_BEGIN_INSTR(Block, blockop)
1492 executedBlocks |= instr->blockop.block;
1493 QML_V4_END_INSTR(Block, blockop)
1495 // XXX not applicable in v8
1496 QML_V4_BEGIN_INSTR(InitString, initstring)
1497 // if (!identifiers[instr->initstring.offset].identifier) {
1498 // quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
1499 // QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
1501 // QString str = QString::fromRawData(strdata, len);
1503 // // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
1505 QML_V4_END_INSTR(InitString, initstring)
1507 QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
1508 registers[instr->cleanup.reg].cleanup();
1509 QML_V4_END_INSTR(CleanupRegister, cleanup)
1511 #ifdef QML_THREADED_INTERPRETER
1515 qFatal("QV4: Unknown instruction %d encountered.", instr->common.type);
1522 Q_ASSERT(!"Unreachable code reached");
1526 delete testBindingSource;
1529 while (cleanupRegisterMask) {
1530 if (cleanupRegisterMask & 0x1)
1531 registers[reg].cleanup();
1534 cleanupRegisterMask >>= 1;