diff options
Diffstat (limited to 'src/declarative/qml/v4')
-rw-r--r-- | src/declarative/qml/v4/qv4bindings.cpp | 1615 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4bindings_p.h | 155 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4compiler.cpp | 1419 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4compiler_p.h | 105 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4compiler_p_p.h | 246 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4instruction.cpp | 421 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4instruction_p.h | 435 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4ir.cpp | 883 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4ir_p.h | 605 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4irbuilder.cpp | 1305 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4irbuilder_p.h | 240 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4program_p.h | 123 | ||||
-rw-r--r-- | src/declarative/qml/v4/v4.pri | 15 |
13 files changed, 0 insertions, 7567 deletions
diff --git a/src/declarative/qml/v4/qv4bindings.cpp b/src/declarative/qml/v4/qv4bindings.cpp deleted file mode 100644 index ecd18cd73f..0000000000 --- a/src/declarative/qml/v4/qv4bindings.cpp +++ /dev/null @@ -1,1615 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// #define REGISTER_CLEANUP_DEBUG - -#include "qv4bindings_p.h" -#include "qv4program_p.h" -#include "qv4compiler_p.h" -#include "qv4compiler_p_p.h" - -#include <private/qdeclarativeaccessors_p.h> -#include <private/qdeclarativeprofilerservice_p.h> -#include <private/qdeclarativemetatype_p.h> -#include <private/qdeclarativetrace_p.h> -#include <private/qdeclarativestringconverters_p.h> - -#include <QtDeclarative/qdeclarativeinfo.h> -#include <QtCore/qnumeric.h> -#include <QtCore/qmath.h> -#include <math.h> // ::fmod - -QT_BEGIN_NAMESPACE - -using namespace QDeclarativeJS; - -namespace { -struct Register { - typedef QDeclarativeRegisterType Type; - - void setUndefined() { dataType = UndefinedType; } - void setNaN() { setqreal(qSNaN()); } - bool isUndefined() const { return dataType == UndefinedType; } - - void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; } - QObject *getQObject() const { return qobjectValue; } - - void setqreal(qreal v) { qrealValue = v; dataType = QRealType; } - qreal getqreal() const { return qrealValue; } - qreal &getqrealref() { return qrealValue; } - - void setint(int v) { intValue = v; dataType = IntType; } - int getint() const { return intValue; } - int &getintref() { return intValue; } - - void setbool(bool v) { boolValue = v; dataType = BoolType; } - bool getbool() const { return boolValue; } - bool &getboolref() { return boolValue; } - - QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } - QString *getstringptr() { return (QString *)typeDataPtr(); } - QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } - QColor *getcolorptr() { return (QColor *)typeDataPtr(); } - const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } - const QString *getstringptr() const { return (QString *)typeDataPtr(); } - const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } - const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); } - - void *typeDataPtr() { return (void *)&data; } - void *typeMemory() { return (void *)data; } - const void *typeDataPtr() const { return (void *)&data; } - const void *typeMemory() const { return (void *)data; } - - Type gettype() const { return dataType; } - void settype(Type t) { dataType = t; } - - Type dataType; // Type of data - union { - QObject *qobjectValue; - qreal qrealValue; - int intValue; - bool boolValue; - void *data[sizeof(QVariant)]; - qint64 q_for_alignment_1; - double q_for_alignment_2; - }; - - inline void cleanup(); - inline void cleanupString(); - inline void cleanupUrl(); - inline void cleanupColor(); - inline void cleanupVariant(); - - inline void copy(const Register &other); - inline void init(Type type); -#ifdef REGISTER_CLEANUP_DEBUG - Register() { - type = 0; - } - - ~Register() { - if (dataType >= FirstCleanupType) - qWarning("Register leaked of type %d", dataType); - } -#endif -}; - -void Register::cleanup() -{ - if (dataType >= FirstCleanupType) { - if (dataType == QStringType) { - getstringptr()->~QString(); - } else if (dataType == QUrlType) { - geturlptr()->~QUrl(); - } else if (dataType == QColorType) { - getcolorptr()->~QColor(); - } else if (dataType == QVariantType) { - getvariantptr()->~QVariant(); - } - } - setUndefined(); -} - -void Register::cleanupString() -{ - getstringptr()->~QString(); - setUndefined(); -} - -void Register::cleanupUrl() -{ - geturlptr()->~QUrl(); - setUndefined(); -} - -void Register::cleanupColor() -{ - getcolorptr()->~QColor(); - setUndefined(); -} - -void Register::cleanupVariant() -{ - getvariantptr()->~QVariant(); - setUndefined(); -} - -void Register::copy(const Register &other) -{ - *this = other; - if (other.dataType >= FirstCleanupType) { - if (other.dataType == QStringType) - new (getstringptr()) QString(*other.getstringptr()); - else if (other.dataType == QUrlType) - new (geturlptr()) QUrl(*other.geturlptr()); - else if (other.dataType == QColorType) - new (getcolorptr()) QColor(*other.getcolorptr()); - else if (other.dataType == QVariantType) - new (getvariantptr()) QVariant(*other.getvariantptr()); - } -} - -void Register::init(Type type) -{ - dataType = type; - if (dataType >= FirstCleanupType) { - if (dataType == QStringType) - new (getstringptr()) QString(); - else if (dataType == QUrlType) - new (geturlptr()) QUrl(); - else if (dataType == QColorType) - new (getcolorptr()) QColor(); - else if (dataType == QVariantType) - new (getvariantptr()) QVariant(); - } -} - -} // end of anonymous namespace - -QV4Bindings::QV4Bindings(const char *programData, - QDeclarativeContextData *context, - QDeclarativeRefCount *ref) -: subscriptions(0), program(0), dataRef(0), bindings(0) -{ - program = (QV4Program *)programData; - dataRef = ref; - if (dataRef) dataRef->addref(); - - if (program) { - subscriptions = new Subscription[program->subscriptions]; - bindings = new Binding[program->bindings]; - - QDeclarativeAbstractExpression::setContext(context); - } -} - -QV4Bindings::~QV4Bindings() -{ - delete [] bindings; - delete [] subscriptions; subscriptions = 0; - if (dataRef) dataRef->release(); -} - -QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *target, - QObject *scope, int property, - int line, int column) -{ - Binding *rv = bindings + index; - - rv->index = index; - rv->property = property; - rv->target = target; - rv->scope = scope; - rv->line = line; - rv->column = column; - rv->parent = this; - - addref(); // This is decremented in Binding::destroy() - - return rv; -} - -void QV4Bindings::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) -{ - if (enabled != e) { - enabled = e; - - if (e) update(flags); - } -} - -void QV4Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) -{ - parent->run(this, flags); -} - -void QV4Bindings::Binding::destroy() -{ - enabled = false; - removeFromObject(); - clear(); - removeError(); - parent->release(); -} - -int QV4Bindings::Binding::propertyIndex() const -{ - //mask out the type information set for value types - return property & 0xFF00FFFF; -} - -QObject *QV4Bindings::Binding::object() const -{ - return target; -} - -void QV4Bindings::Subscription::subscriptionCallback(QDeclarativeNotifierEndpoint *e) -{ - Subscription *s = static_cast<Subscription *>(e); - s->bindings->subscriptionNotify(s->method); -} - -void QV4Bindings::subscriptionNotify(int id) -{ - QV4Program::BindingReferenceList *list = program->signalTable(id); - - for (quint32 ii = 0; ii < list->count; ++ii) { - QV4Program::BindingReference *bindingRef = list->bindings + ii; - - Binding *binding = bindings + bindingRef->binding; - - if (binding->executedBlocks & bindingRef->blockMask) { - run(binding, QDeclarativePropertyPrivate::DontRemoveBinding); - } - } -} - -void QV4Bindings::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags) -{ - if (!binding->enabled) - return; - - QDeclarativeContextData *context = QDeclarativeAbstractExpression::context(); - if (!context || !context->isValid()) - return; - - QDeclarativeTrace trace("V4 Binding Update"); - trace.addDetail("URL", context->url); - trace.addDetail("Line", binding->line); - trace.addDetail("Column", binding->column); - - QDeclarativeBindingProfiler prof(context->urlString, binding->line, binding->column); - - if (binding->updating) { - QString name; - if (binding->property & 0xFFFF0000) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); - - QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - - name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name()); - name.append(QLatin1String(".")); - name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name())); - } else { - name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); - } - qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name); - return; - } - - binding->updating = true; - if (binding->property & 0xFFFF0000) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); - - QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - vt->read(binding->target, binding->property & 0xFFFF); - - QObject *target = vt; - run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags); - - vt->write(binding->target, binding->property & 0xFFFF, flags); - } else { - run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags); - } - binding->updating = false; -} - - -void QV4Bindings::unsubscribe(int subIndex) -{ - Subscription *sub = (subscriptions + subIndex); - sub->disconnect(); -} - -void QV4Bindings::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex) -{ - unsubscribe(subIndex); - - if (p->idValues[idIndex]) { - Subscription *sub = (subscriptions + subIndex); - sub->bindings = this; - sub->method = subIndex; - sub->connect(&p->idValues[idIndex].bindings); - } -} - -void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex) -{ - Subscription *sub = (subscriptions + subIndex); - if (sub->isConnected(o, notifyIndex)) - return; - sub->bindings = this; - sub->method = subIndex; - if (o) - sub->connect(o, notifyIndex); - else - sub->disconnect(); -} - -// Conversion functions - these MUST match the QtScript expression path -inline static qreal toReal(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return reg->getqreal(); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toReal(); - } else { - if (ok) *ok = false; - return 0; - } -} - -inline static QString toString(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return QString::number(reg->getqreal()); - } else if (type == QMetaType::Int) { - return QString::number(reg->getint()); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toString(); - } else if (type == QMetaType::QString) { - return *reg->getstringptr(); - } else { - if (ok) *ok = false; - return QString(); - } -} - -inline static bool toBool(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::Bool) { - return reg->getbool(); - } else if (type == qMetaTypeId<QVariant>()) { - return reg->getvariantptr()->toBool(); - } else { - if (ok) *ok = false; - return false; - } -} - -inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0) -{ - if (ok) *ok = true; - - QUrl base; - if (type == qMetaTypeId<QVariant>()) { - QVariant *var = reg->getvariantptr(); - int vt = var->type(); - if (vt == QVariant::Url) { - base = var->toUrl(); - } else if (vt == QVariant::ByteArray) { - // Preserve any valid percent-encoded octets supplied by the source - base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode); - } else if (vt == QVariant::String) { - base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode); - } else { - if (ok) *ok = false; - return QUrl(); - } - } else if (type == QMetaType::QString) { - base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode); - } else { - if (ok) *ok = false; - return QUrl(); - } - - if (!base.isEmpty() && base.isRelative()) - return context->url.resolved(base); - else - return base; -} - -static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4) -{ - QVariant qtscript = qtscriptRaw; - - if (qtscript.userType() == v4.userType()) { - } else if (qtscript.canConvert((QVariant::Type)v4.userType())) { - qtscript.convert((QVariant::Type)v4.userType()); - } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) { - qtscript = qVariantFromValue<QObject *>(0); - } else { - return false; - } - - int type = qtscript.userType(); - - if (type == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) { - return QDeclarativeMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData()); - } else if (type == QMetaType::Double) { - - double la = qvariant_cast<double>(qtscript); - double lr = qvariant_cast<double>(v4); - - return la == lr || (qIsNaN(la) && qIsNaN(lr)); - - } else if (type == QMetaType::Float) { - - float la = qvariant_cast<float>(qtscript); - float lr = qvariant_cast<float>(v4); - - return la == lr || (qIsNaN(la) && qIsNaN(lr)); - - } else { - return qtscript == v4; - } -} - -QByteArray testResultToString(const QVariant &result, bool undefined) -{ - if (undefined) { - return "undefined"; - } else { - QString rv; - QDebug d(&rv); - d << result; - return rv.toUtf8(); - } -} - -static void testBindingResult(const QString &binding, int line, int column, - QDeclarativeContextData *context, QObject *scope, - const Register &result, int resultType) -{ - QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding); - bool isUndefined = false; - QVariant value = expression.evaluate(&isUndefined); - - bool iserror = false; - QByteArray qtscriptResult; - QByteArray v4Result; - - if (expression.hasError()) { - iserror = true; - qtscriptResult = "exception"; - } else { - qtscriptResult = testResultToString(value, isUndefined); - } - - if (isUndefined && result.isUndefined()) { - return; - } else if(isUndefined != result.isUndefined()) { - iserror = true; - } - - QVariant v4value; - if (!result.isUndefined()) { - switch (resultType) { - case QMetaType::QString: - v4value = *result.getstringptr(); - break; - case QMetaType::QUrl: - v4value = *result.geturlptr(); - break; - case QMetaType::QObjectStar: - v4value = qVariantFromValue<QObject *>(result.getQObject()); - break; - case QMetaType::Bool: - v4value = result.getbool(); - break; - case QMetaType::Int: - v4value = result.getint(); - break; - case QMetaType::QReal: - v4value = result.getqreal(); - break; - default: - if (resultType == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) { - v4value = QVariant(QDeclarativeMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr()); - } else { - iserror = true; - v4Result = "Unknown V4 type"; - } - } - } - if (v4Result.isEmpty()) - v4Result = testResultToString(v4value, result.isUndefined()); - - if (!testCompareVariants(value, v4value)) - iserror = true; - - if (iserror) { - qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; - - qWarning().nospace() << " Binding: " << binding; - qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); - qWarning().nospace() << " V4: " << v4Result.constData(); - } -} - -static void testBindingException(const QString &binding, int line, int column, - QDeclarativeContextData *context, QObject *scope) -{ - QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding); - bool isUndefined = false; - QVariant value = expression.evaluate(&isUndefined); - - if (!expression.hasError()) { - QByteArray qtscriptResult = testResultToString(value, isUndefined); - qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; - qWarning().nospace() << " Binding: " << binding; - qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); - qWarning().nospace() << " V4: exception"; - } -} - -static void throwException(int id, QDeclarativeDelayedError *error, - QV4Program *program, QDeclarativeContextData *context, - const QString &description = QString()) -{ - error->error.setUrl(context->url); - if (description.isEmpty()) - error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object")); - else - error->error.setDescription(description); - if (id != 0xFF) { - quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); - error->error.setLine((e >> 32) & 0xFFFFFFFF); - error->error.setColumn(e & 0xFFFFFFFF); - } else { - error->error.setLine(-1); - error->error.setColumn(-1); - } - if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine))) - QDeclarativeEnginePrivate::warning(context->engine, error->error); -} - -const qreal QV4Bindings::D32 = 4294967296.0; - -qint32 QV4Bindings::toInt32(qreal n) -{ - if (qIsNaN(n) || qIsInf(n) || (n == 0)) - return 0; - - double sign = (n < 0) ? -1.0 : 1.0; - qreal abs_n = fabs(n); - - n = ::fmod(sign * ::floor(abs_n), D32); - const double D31 = D32 / 2.0; - - if (sign == -1 && n < -D31) - n += D32; - - else if (sign != -1 && n >= D31) - n -= D32; - - return qint32 (n); -} - -inline quint32 QV4Bindings::toUint32(qreal n) -{ - if (qIsNaN(n) || qIsInf(n) || (n == 0)) - return 0; - - double sign = (n < 0) ? -1.0 : 1.0; - qreal abs_n = fabs(n); - - n = ::fmod(sign * ::floor(abs_n), D32); - - if (n < 0) - n += D32; - - return quint32 (n); -} - -#define THROW_EXCEPTION_STR(id, str) { \ - if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \ - throwException((id), error, program, context, (str)); \ - goto exceptionExit; \ -} - -#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString()) - -#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg)) -#define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg)) - -#define STRING_REGISTER(reg) { \ - registers[(reg)].settype(QStringType); \ - MARK_REGISTER(reg); \ -} - -#define URL_REGISTER(reg) { \ - registers[(reg)].settype(QUrlType); \ - MARK_REGISTER(reg); \ -} - -#define COLOR_REGISTER(reg) { \ - registers[(reg)].settype(QColorType); \ - MARK_REGISTER(reg); \ -} - -#define VARIANT_REGISTER(reg) { \ - registers[(reg)].settype(QVariantType); \ - MARK_REGISTER(reg); \ -} - -#ifdef QML_THREADED_INTERPRETER -void **QV4Bindings::getDecodeInstrTable() -{ - static void **decode_instr; - if (!decode_instr) { - QV4Bindings *dummy = new QV4Bindings(0, 0, 0); - quint32 executedBlocks = 0; - dummy->run(0, executedBlocks, 0, 0, 0, 0, - QDeclarativePropertyPrivate::BypassInterceptor, - &decode_instr); - dummy->release(); - } - return decode_instr; -} -#endif - -void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, - QDeclarativeContextData *context, QDeclarativeDelayedError *error, - QObject *scope, QObject *output, - QDeclarativePropertyPrivate::WriteFlags storeFlags -#ifdef QML_THREADED_INTERPRETER - ,void ***table -#endif - ) -{ -#ifdef QML_THREADED_INTERPRETER - if (table) { - static void *decode_instr[] = { - FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR) - }; - - *table = decode_instr; - return; - } -#endif - - - error->removeError(); - - Register registers[32]; - quint32 cleanupRegisterMask = 0; - - executedBlocks = 0; - - const char *code = program->instructions(); - code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump); - const V4Instr *instr = reinterpret_cast<const V4Instr *>(code); - - const char *data = program->data(); - - QString *testBindingSource = 0; - bool testBinding = false; - int bindingLine = 0; - int bindingColumn = 0; - -#ifdef QML_THREADED_INTERPRETER - goto *instr->common.code; -#else - for (;;) { - switch (instr->common.type) { -#endif - - QML_V4_BEGIN_INSTR(Noop, common) - QML_V4_END_INSTR(Noop, common) - - QML_V4_BEGIN_INSTR(BindingId, id) - bindingLine = instr->id.line; - bindingColumn = instr->id.column; - QML_V4_END_INSTR(BindingId, id) - - QML_V4_BEGIN_INSTR(SubscribeId, subscribeop) - subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset); - QML_V4_END_INSTR(SubscribeId, subscribeop) - - QML_V4_BEGIN_INSTR(Subscribe, subscribeop) - { - QObject *o = 0; - const Register &object = registers[instr->subscribeop.reg]; - if (!object.isUndefined()) o = object.getQObject(); - subscribe(o, instr->subscribeop.index, instr->subscribeop.offset); - } - QML_V4_END_INSTR(Subscribe, subscribeop) - - QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe) - { - Register ® = registers[instr->fetchAndSubscribe.reg]; - - if (reg.isUndefined()) - THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId); - - QObject *object = reg.getQObject(); - if (!object) { - reg.setUndefined(); - } else { - int subIdx = instr->fetchAndSubscribe.subscription; - Subscription *sub = 0; - if (subIdx != -1) { - sub = (subscriptions + subIdx); - sub->bindings = this; - sub->method = subIdx; - } - reg.init((Register::Type)instr->fetchAndSubscribe.valueType); - if (instr->fetchAndSubscribe.valueType >= FirstCleanupType) - MARK_REGISTER(instr->fetchAndSubscribe.reg); - QDeclarativeAccessors *accessors = instr->fetchAndSubscribe.property.accessors; - accessors->read(object, instr->fetchAndSubscribe.property.accessorData, - reg.typeDataPtr()); - - if (accessors->notifier) { - QDeclarativeNotifier *notifier = 0; - accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier); - if (notifier) sub->connect(notifier); - } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) { - sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex); - } - } - } - QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe) - - QML_V4_BEGIN_INSTR(LoadId, load) - registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data()); - QML_V4_END_INSTR(LoadId, load) - - QML_V4_BEGIN_INSTR(LoadScope, load) - registers[instr->load.reg].setQObject(scope); - QML_V4_END_INSTR(LoadScope, load) - - QML_V4_BEGIN_INSTR(LoadRoot, load) - registers[instr->load.reg].setQObject(context->contextObject); - QML_V4_END_INSTR(LoadRoot, load) - - QML_V4_BEGIN_INSTR(LoadAttached, attached) - { - const Register &input = registers[instr->attached.reg]; - Register &output = registers[instr->attached.output]; - if (input.isUndefined()) - THROW_EXCEPTION(instr->attached.exceptionId); - - QObject *object = registers[instr->attached.reg].getQObject(); - if (!object) { - output.setUndefined(); - } else { - QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true); - Q_ASSERT(attached); - output.setQObject(attached); - } - } - QML_V4_END_INSTR(LoadAttached, attached) - - QML_V4_BEGIN_INSTR(UnaryNot, unaryop) - { - registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool()); - } - QML_V4_END_INSTR(UnaryNot, unaryop) - - QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop) - { - registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal()); - } - QML_V4_END_INSTR(UnaryMinusReal, unaryop) - - QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop) - { - registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint()); - } - QML_V4_END_INSTR(UnaryMinusInt, unaryop) - - QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop) - { - registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal()); - } - QML_V4_END_INSTR(UnaryPlusReal, unaryop) - - QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop) - { - registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint()); - } - QML_V4_END_INSTR(UnaryPlusInt, unaryop) - - QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setint(src.getbool()); - } - QML_V4_END_INSTR(ConvertBoolToInt, unaryop) - - QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setqreal(src.getbool()); - } - QML_V4_END_INSTR(ConvertBoolToReal, unaryop) - - QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) { - output.setUndefined(); - } else { - new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false")); - STRING_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertBoolToString, unaryop) - - QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setbool(src.getint()); - } - QML_V4_END_INSTR(ConvertIntToBool, unaryop) - - QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setqreal(qreal(src.getint())); - } - QML_V4_END_INSTR(ConvertIntToReal, unaryop) - - QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) { - output.setUndefined(); - } else { - new (output.getstringptr()) QString(QString::number(src.getint())); - STRING_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertIntToString, unaryop) - - QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setbool(src.getqreal() != 0); - } - QML_V4_END_INSTR(ConvertRealToBool, unaryop) - - QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setint(toInt32(src.getqreal())); - } - QML_V4_END_INSTR(ConvertRealToInt, unaryop) - - QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - new (output.getstringptr()) QString(QString::number(src.getqreal())); - STRING_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertRealToString, unaryop) - - QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. - // Ideally we should just call the methods in the QScript namespace directly. - QJSValue tmp(*src.getstringptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupString(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - output.setbool(tmp.toBool()); - } - } - QML_V4_END_INSTR(ConvertStringToBool, unaryop) - - QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. - // Ideally we should just call the methods in the QScript namespace directly. - QJSValue tmp(*src.getstringptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupString(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - output.setint(tmp.toInt()); - } - } - QML_V4_END_INSTR(ConvertStringToInt, unaryop) - - QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. - // Ideally we should just call the methods in the QScript namespace directly. - QJSValue tmp(*src.getstringptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupString(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - output.setqreal(tmp.toNumber()); - } - } - QML_V4_END_INSTR(ConvertStringToReal, unaryop) - - QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QString tmp(*src.getstringptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupString(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - QUrl *urlPtr = output.geturlptr(); - new (urlPtr) QUrl(); - urlPtr->setEncodedUrl(tmp.toUtf8(), QUrl::TolerantMode); - - URL_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertStringToUrl, unaryop) - - QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QString tmp(*src.getstringptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupString(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - QColor *colorPtr = output.getcolorptr(); - new (colorPtr) QColor(QDeclarativeStringConverters::colorFromString(tmp)); - - COLOR_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertStringToUrl, unaryop) - - QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QUrl tmp(*src.geturlptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupUrl(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - output.setbool(!tmp.isEmpty()); - } - } - QML_V4_END_INSTR(ConvertUrlToBool, unaryop) - - QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QUrl tmp(*src.geturlptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupUrl(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - new (output.getstringptr()) QString(tmp.toString()); - STRING_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertUrlToString, unaryop) - - QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - // for compatibility with color behavior in v8, always true - output.setbool(true); - } - } - QML_V4_END_INSTR(ConvertColorToBool, unaryop) - - QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - // ### NaN - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QColor tmp(*src.getcolorptr()); - if (instr->unaryop.src == instr->unaryop.output) { - output.cleanupColor(); - MARK_CLEAN_REGISTER(instr->unaryop.output); - } - // to maintain behaviour with QtQuick 1.0, we just output normal toString() value. - new (output.getstringptr()) QString(QVariant(tmp).toString()); - STRING_REGISTER(instr->unaryop.output); - } - } - QML_V4_END_INSTR(ConvertColorToString, unaryop) - - QML_V4_BEGIN_INSTR(ResolveUrl, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) { - output.setUndefined(); - } else { - const QUrl tmp(*src.geturlptr()); - if (instr->unaryop.src == instr->unaryop.output) { - *output.geturlptr() = context->resolvedUrl(tmp); - } else { - new (output.geturlptr()) QUrl(context->resolvedUrl(tmp)); - URL_REGISTER(instr->unaryop.output); - } - } - } - QML_V4_END_INSTR(ResolveUrl, unaryop) - - QML_V4_BEGIN_INSTR(MathSinReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setqreal(qSin(src.getqreal())); - } - QML_V4_END_INSTR(MathSinReal, unaryop) - - QML_V4_BEGIN_INSTR(MathCosReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setqreal(qCos(src.getqreal())); - } - QML_V4_END_INSTR(MathCosReal, unaryop) - - QML_V4_BEGIN_INSTR(MathRoundReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setint(qRound(src.getqreal())); - } - QML_V4_END_INSTR(MathRoundReal, unaryop) - - QML_V4_BEGIN_INSTR(MathFloorReal, unaryop) - { - const Register &src = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (src.isUndefined()) output.setUndefined(); - else output.setint(qFloor(src.getqreal())); - } - QML_V4_END_INSTR(MathFloorReal, unaryop) - - QML_V4_BEGIN_INSTR(MathPIReal, unaryop) - { - static const qreal qmlPI = 2.0 * qAsin(1.0); - Register &output = registers[instr->unaryop.output]; - output.setqreal(qmlPI); - } - QML_V4_END_INSTR(MathPIReal, unaryop) - - QML_V4_BEGIN_INSTR(LoadReal, real_value) - registers[instr->real_value.reg].setqreal(instr->real_value.value); - QML_V4_END_INSTR(LoadReal, real_value) - - QML_V4_BEGIN_INSTR(LoadInt, int_value) - registers[instr->int_value.reg].setint(instr->int_value.value); - QML_V4_END_INSTR(LoadInt, int_value) - - QML_V4_BEGIN_INSTR(LoadBool, bool_value) - registers[instr->bool_value.reg].setbool(instr->bool_value.value); - QML_V4_END_INSTR(LoadBool, bool_value) - - QML_V4_BEGIN_INSTR(LoadString, string_value) - { - Register &output = registers[instr->string_value.reg]; - QChar *string = (QChar *)(data + instr->string_value.offset); - new (output.getstringptr()) QString(string, instr->string_value.length); - STRING_REGISTER(instr->string_value.reg); - } - QML_V4_END_INSTR(LoadString, string_value) - - QML_V4_BEGIN_INSTR(EnableV4Test, string_value) - { - testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); - testBinding = true; - } - QML_V4_END_INSTR(String, string_value) - - QML_V4_BEGIN_INSTR(BitAndInt, binaryop) - { - registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() & - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(BitAndInt, binaryop) - - QML_V4_BEGIN_INSTR(BitOrInt, binaryop) - { - registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() | - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(BitAndInt, binaryop) - - QML_V4_BEGIN_INSTR(BitXorInt, binaryop) - { - registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^ - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(BitXorInt, binaryop) - - QML_V4_BEGIN_INSTR(AddReal, binaryop) - { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(AddReal, binaryop) - - QML_V4_BEGIN_INSTR(AddString, binaryop) - { - QString &string = *registers[instr->binaryop.output].getstringptr(); - if (instr->binaryop.output == instr->binaryop.left) { - string += registers[instr->binaryop.right].getstringptr(); - } else { - string = *registers[instr->binaryop.left].getstringptr() + - *registers[instr->binaryop.right].getstringptr(); - } - } - QML_V4_END_INSTR(AddString, binaryop) - - QML_V4_BEGIN_INSTR(SubReal, binaryop) - { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(SubReal, binaryop) - - QML_V4_BEGIN_INSTR(MulReal, binaryop) - { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(MulReal, binaryop) - - QML_V4_BEGIN_INSTR(DivReal, binaryop) - { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(DivReal, binaryop) - - QML_V4_BEGIN_INSTR(ModReal, binaryop) - { - Register &target = registers[instr->binaryop.output]; - const Register &left = registers[instr->binaryop.left]; - const Register &right = registers[instr->binaryop.right]; - if (QMetaType::QReal == QMetaType::Float) - target.setqreal(::fmodf(left.getqreal(), right.getqreal())); - else - target.setqreal(::fmod(left.getqreal(), right.getqreal())); - } - QML_V4_END_INSTR(ModInt, binaryop) - - QML_V4_BEGIN_INSTR(LShiftInt, binaryop) - { - registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() << - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(LShiftInt, binaryop) - - QML_V4_BEGIN_INSTR(RShiftInt, binaryop) - { - registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >> - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(RShiftInt, binaryop) - - QML_V4_BEGIN_INSTR(URShiftInt, binaryop) - { - registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >> - registers[instr->binaryop.right].getint()); - } - QML_V4_END_INSTR(URShiftInt, binaryop) - - QML_V4_BEGIN_INSTR(GtReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(GtReal, binaryop) - - QML_V4_BEGIN_INSTR(LtReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(LtReal, binaryop) - - QML_V4_BEGIN_INSTR(GeReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(GeReal, binaryop) - - QML_V4_BEGIN_INSTR(LeReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(LeReal, binaryop) - - QML_V4_BEGIN_INSTR(EqualReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(EqualReal, binaryop) - - QML_V4_BEGIN_INSTR(NotEqualReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(NotEqualReal, binaryop) - - QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(StrictEqualReal, binaryop) - - QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop) - { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != - registers[instr->binaryop.right].getqreal()); - } - QML_V4_END_INSTR(StrictNotEqualReal, binaryop) - - QML_V4_BEGIN_INSTR(GtString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a > b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(GtString, binaryop) - - QML_V4_BEGIN_INSTR(LtString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a < b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(LtString, binaryop) - - QML_V4_BEGIN_INSTR(GeString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a >= b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(GeString, binaryop) - - QML_V4_BEGIN_INSTR(LeString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a <= b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(LeString, binaryop) - - QML_V4_BEGIN_INSTR(EqualString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a == b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(EqualString, binaryop) - - QML_V4_BEGIN_INSTR(NotEqualString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a != b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(NotEqualString, binaryop) - - QML_V4_BEGIN_INSTR(StrictEqualString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a == b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(StrictEqualString, binaryop) - - QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop) - { - const QString &a = *registers[instr->binaryop.left].getstringptr(); - const QString &b = *registers[instr->binaryop.right].getstringptr(); - bool result = a != b; - if (instr->binaryop.left == instr->binaryop.output) { - registers[instr->binaryop.output].cleanupString(); - MARK_CLEAN_REGISTER(instr->binaryop.output); - } - registers[instr->binaryop.output].setbool(result); - } - QML_V4_END_INSTR(StrictNotEqualString, binaryop) - - QML_V4_BEGIN_INSTR(NewString, construct) - { - Register &output = registers[instr->construct.reg]; - new (output.getstringptr()) QString; - STRING_REGISTER(instr->construct.reg); - } - QML_V4_END_INSTR(NewString, construct) - - QML_V4_BEGIN_INSTR(NewUrl, construct) - { - Register &output = registers[instr->construct.reg]; - new (output.geturlptr()) QUrl; - URL_REGISTER(instr->construct.reg); - } - QML_V4_END_INSTR(NewUrl, construct) - - QML_V4_BEGIN_INSTR(Fetch, fetch) - { - Register ® = registers[instr->fetch.reg]; - - if (reg.isUndefined()) - THROW_EXCEPTION(instr->fetch.exceptionId); - - QObject *object = reg.getQObject(); - if (!object) { - THROW_EXCEPTION(instr->fetch.exceptionId); - } else { - reg.init((Register::Type)instr->fetch.valueType); - if (instr->fetch.valueType >= FirstCleanupType) - MARK_REGISTER(instr->fetch.reg); - void *argv[] = { reg.typeDataPtr(), 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); - } - } - QML_V4_END_INSTR(Fetch, fetch) - - QML_V4_BEGIN_INSTR(TestV4Store, storetest) - { - Register &data = registers[instr->storetest.reg]; - testBindingResult(*testBindingSource, bindingLine, bindingColumn, context, - scope, data, instr->storetest.regType); - } - QML_V4_END_INSTR(TestV4Store, storetest) - - QML_V4_BEGIN_INSTR(Store, store) - { - Register &data = registers[instr->store.reg]; - - if (data.isUndefined()) - THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value")); - - int status = -1; - void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; - QMetaObject::metacall(output, QMetaObject::WriteProperty, - instr->store.index, argv); - - goto programExit; - } - QML_V4_END_INSTR(Store, store) - - QML_V4_BEGIN_INSTR(Copy, copy) - registers[instr->copy.reg].copy(registers[instr->copy.src]); - if (registers[instr->copy.reg].gettype() >= FirstCleanupType) - MARK_REGISTER(instr->copy.reg); - QML_V4_END_INSTR(Copy, copy) - - QML_V4_BEGIN_INSTR(Jump, jump) - if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool()) - code += instr->jump.count; - QML_V4_END_INSTR(Jump, jump) - - QML_V4_BEGIN_INSTR(BranchTrue, branchop) - if (registers[instr->branchop.reg].getbool()) - code += instr->branchop.offset; - QML_V4_END_INSTR(BranchTrue, branchop) - - QML_V4_BEGIN_INSTR(BranchFalse, branchop) - if (! registers[instr->branchop.reg].getbool()) - code += instr->branchop.offset; - QML_V4_END_INSTR(BranchFalse, branchop) - - QML_V4_BEGIN_INSTR(Branch, branchop) - code += instr->branchop.offset; - QML_V4_END_INSTR(Branch, branchop) - - QML_V4_BEGIN_INSTR(Block, blockop) - executedBlocks |= instr->blockop.block; - QML_V4_END_INSTR(Block, blockop) - - // XXX not applicable in v8 - QML_V4_BEGIN_INSTR(InitString, initstring) -// if (!identifiers[instr->initstring.offset].identifier) { -// quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); -// QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); - -// QString str = QString::fromRawData(strdata, len); - -// // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); -// } - QML_V4_END_INSTR(InitString, initstring) - - QML_V4_BEGIN_INSTR(CleanupRegister, cleanup) - registers[instr->cleanup.reg].cleanup(); - QML_V4_END_INSTR(CleanupRegister, cleanup) - -#ifdef QML_THREADED_INTERPRETER - // nothing to do -#else - default: - qFatal("QV4: Unknown instruction %d encountered.", instr->common.type); - break; - } // switch - - } // while -#endif - - Q_ASSERT(!"Unreachable code reached"); - -programExit: -exceptionExit: - delete testBindingSource; - - int reg = 0; - while (cleanupRegisterMask) { - if (cleanupRegisterMask & 0x1) - registers[reg].cleanup(); - - reg++; - cleanupRegisterMask >>= 1; - } -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qv4bindings_p.h b/src/declarative/qml/v4/qv4bindings_p.h deleted file mode 100644 index a447481a4c..0000000000 --- a/src/declarative/qml/v4/qv4bindings_p.h +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4BINDINGS_P_H -#define QV4BINDINGS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qdeclarativeexpression_p.h" -#include "private/qdeclarativebinding_p.h" -#include "private/qv4instruction_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -struct QV4Program; -class QV4Bindings : public QDeclarativeAbstractExpression, - public QDeclarativeRefCount -{ - Q_DECLARE_TR_FUNCTIONS(QV4Bindings) -public: - QV4Bindings(const char *program, QDeclarativeContextData *context, - QDeclarativeRefCount *); - virtual ~QV4Bindings(); - - QDeclarativeAbstractBinding *configBinding(int index, QObject *target, - QObject *scope, int property, - int line, int column); - -#ifdef QML_THREADED_INTERPRETER - static void **getDecodeInstrTable(); -#endif - -private: - Q_DISABLE_COPY(QV4Bindings) - - struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError { - Binding() : enabled(false), updating(0), property(0), - scope(0), target(0), executedBlocks(0), parent(0) {} - - // Inherited from QDeclarativeAbstractBinding - virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); - virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); - virtual void destroy(); - virtual int propertyIndex() const; - virtual QObject *object() const; - - int index:30; - bool enabled:1; - bool updating:1; - // Encoding of property is coreIndex | (propType << 16) | (valueTypeIndex << 24) - // propType and valueTypeIndex are only set if the property is a value type property - int property; - QObject *scope; - int line; - int column; - QObject *target; - quint32 executedBlocks; - - QV4Bindings *parent; - }; - - class Subscription : public QDeclarativeNotifierEndpoint - { - public: - Subscription() : bindings(0), method(-1) { callback = &subscriptionCallback; } - static void subscriptionCallback(QDeclarativeNotifierEndpoint *e); - QV4Bindings *bindings; - int method; - }; - friend class Subscription; - - Subscription *subscriptions; - - void subscriptionNotify(int); - void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags); - - QV4Program *program; - QDeclarativeRefCount *dataRef; - Binding *bindings; - - void init(); - void run(int instr, quint32 &executedBlocks, QDeclarativeContextData *context, - QDeclarativeDelayedError *error, QObject *scope, QObject *output, - QDeclarativePropertyPrivate::WriteFlags storeFlags -#ifdef QML_THREADED_INTERPRETER - , void ***decode_instr = 0 -#endif - ); - - - inline void unsubscribe(int subIndex); - inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex); - inline void subscribe(QObject *o, int notifyIndex, int subIndex); - - inline static qint32 toInt32(qreal n); - static const qreal D32; - static quint32 toUint32(qreal n); - -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4BINDINGS_P_H - diff --git a/src/declarative/qml/v4/qv4compiler.cpp b/src/declarative/qml/v4/qv4compiler.cpp deleted file mode 100644 index 0a0269d903..0000000000 --- a/src/declarative/qml/v4/qv4compiler.cpp +++ /dev/null @@ -1,1419 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4compiler_p.h" -#include "qv4compiler_p_p.h" -#include "qv4program_p.h" -#include "qv4ir_p.h" -#include "qv4irbuilder_p.h" - -#include <private/qdeclarativejsast_p.h> -#include <private/qdeclarativeaccessors_p.h> -#include <private/qdeclarativejsengine_p.h> - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP) -DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER) -DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL) -DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) -DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST) - -static bool qmlBindingsTest = false; -static bool qmlEnableV4 = true; - -using namespace QDeclarativeJS; -QV4CompilerPrivate::QV4CompilerPrivate() - : _function(0) , _block(0) , _discarded(false), registerCount(0) -{ -} - -// -// tracing -// -void QV4CompilerPrivate::trace(int line, int column) -{ - bytecode.clear(); - - this->currentReg = _function->tempCount; - this->registerCount = qMax(this->registerCount, this->currentReg); - - foreach (IR::BasicBlock *bb, _function->basicBlocks) { - if (! bb->isTerminated() && (bb->index + 1) < _function->basicBlocks.size()) - bb->JUMP(_function->basicBlocks.at(bb->index + 1)); - } - - QVector<IR::BasicBlock *> blocks; - trace(&blocks); - currentBlockMask = 0x00000001; - - - for (int i = 0; !_discarded && i < blocks.size(); ++i) { - IR::BasicBlock *block = blocks.at(i); - IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0; - if (IR::Stmt *terminator = block->terminator()) { - if (IR::CJump *cj = terminator->asCJump()) { - if (cj->iffalse != next) { - IR::Jump *jump = _function->pool->New<IR::Jump>(); - jump->init(cj->iffalse); - block->statements.append(jump); - } - } else if (IR::Jump *j = terminator->asJump()) { - if (j->target == next) { - block->statements.resize(block->statements.size() - 1); - } - } - } - - block->offset = bytecode.size(); - - if (bytecode.isEmpty()) { - if (qmlBindingsTest || bindingsDump()) { - Instr::BindingId id; - id.column = column; - id.line = line; - gen(id); - } - - if (qmlBindingsTest) { - QString str = expression->expression.asScript(); - QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); - int offset = data.count(); - data += strdata; - - Instr::EnableV4Test test; - test.reg = 0; - test.offset = offset; - test.length = str.length(); - gen(test); - } - } - - bool usic = false; - int patchesCount = patches.count(); - qSwap(usedSubscriptionIdsChanged, usic); - - int blockopIndex = bytecode.size(); - Instr::Block blockop; - blockop.block = currentBlockMask; - gen(blockop); - - foreach (IR::Stmt *s, block->statements) { - if (! _discarded) - s->accept(this); - } - - qSwap(usedSubscriptionIdsChanged, usic); - - if (usic) { - if (currentBlockMask == 0x80000000) { - discard(); - return; - } - currentBlockMask <<= 1; - } else if (! _discarded) { - const int adjust = bytecode.remove(blockopIndex); - // Correct patches - for (int ii = patchesCount; ii < patches.count(); ++ii) - patches[ii].offset -= adjust; - } - } - -#ifdef DEBUG_IR_STRUCTURE - IR::IRDump dump; - for (int i = 0; i < blocks.size(); ++i) { - dump.basicblock(blocks.at(i)); - } -#endif - - - if (! _discarded) { - // back patching - foreach (const Patch &patch, patches) { - V4Instr &instr = bytecode[patch.offset]; - int size = V4Instr::size(instructionType(&instr)); - instr.branchop.offset = patch.block->offset - patch.offset - size; - } - - patches.clear(); - } -} - -void QV4CompilerPrivate::trace(QVector<IR::BasicBlock *> *blocks) -{ - for (int i = 0; i < _function->basicBlocks.size(); ++i) { - IR::BasicBlock *block = _function->basicBlocks.at(i); - - while (! blocks->contains(block)) { - blocks->append(block); - - if (IR::Stmt *terminator = block->terminator()) { - if (IR::CJump *cj = terminator->asCJump()) - block = cj->iffalse; - else if (IR::Jump *j = terminator->asJump()) - block = j->target; - } - } - } -} - -void QV4CompilerPrivate::traceExpression(IR::Expr *e, quint8 r) -{ - if (!e) { - discard(); - } else { - qSwap(currentReg, r); - e->accept(this); - qSwap(currentReg, r); - } -} - -// -// expressions -// -void QV4CompilerPrivate::visitConst(IR::Const *e) -{ - switch (e->type) { - case IR::BoolType: { - Instr::LoadBool i; - i.reg = currentReg; - i.value = e->value; - gen(i); - } break; - - case IR::IntType: { - Instr::LoadInt i; - i.reg = currentReg; - i.value = e->value; - gen(i); - } break; - - case IR::RealType: { - Instr::LoadReal i; - i.reg = currentReg; - i.value = e->value; - gen(i); - } break; - - default: - if (qmlVerboseCompiler()) - qWarning() << Q_FUNC_INFO << "unexpected type"; - discard(); - } -} - -void QV4CompilerPrivate::visitString(IR::String *e) -{ - registerLiteralString(currentReg, e->value); -} - -void QV4CompilerPrivate::visitName(IR::Name *e) -{ - if (e->base) { - // fetch the object and store it in reg. - traceExpression(e->base, currentReg); - } else { - _subscribeName.clear(); - } - - if (e->storage == IR::Name::RootStorage) { - - Instr::LoadRoot instr; - instr.reg = currentReg; - gen(instr); - - if (e->symbol == IR::Name::IdObject) { - // The ID is a reference to the root object - return; - } - - } else if (e->storage == IR::Name::ScopeStorage) { - - Instr::LoadScope instr; - instr.reg = currentReg; - gen(instr); - - _subscribeName << contextName(); - - } else if (e->storage == IR::Name::IdStorage) { - - Instr::LoadId instr; - instr.reg = currentReg; - instr.index = e->idObject->idIndex; - gen(instr); - - _subscribeName << QLatin1String("$$$ID_") + *e->id; - - if (blockNeedsSubscription(_subscribeName)) { - Instr::SubscribeId sub; - sub.reg = currentReg; - sub.offset = subscriptionIndex(_subscribeName); - sub.index = instr.index; - gen(sub); - } - - return; - } else { - // No action needed - } - - switch (e->symbol) { - case IR::Name::Unbound: - case IR::Name::IdObject: - case IR::Name::Slot: - case IR::Name::Object: { - Q_ASSERT(!"Unreachable"); - discard(); - } break; - - case IR::Name::AttachType: { - _subscribeName << *e->id; - - Instr::LoadAttached attached; - attached.output = currentReg; - attached.reg = currentReg; - attached.exceptionId = exceptionId(e->line, e->column); - if (e->declarativeType->attachedPropertiesId() == -1) - discard(); - attached.id = e->declarativeType->attachedPropertiesId(); - gen(attached); - } break; - - case IR::Name::Property: { - _subscribeName << *e->id; - - if (e->property->coreIndex == -1) { - QMetaProperty prop; - e->property->load(prop, QDeclarativeEnginePrivate::get(engine)); - } - - const int propTy = e->property->propType; - QDeclarativeRegisterType regType; - - switch (propTy) { - case QMetaType::QReal: - regType = QRealType; - break; - case QMetaType::Bool: - regType = BoolType; - break; - case QMetaType::Int: - regType = IntType; - break; - case QMetaType::QString: - regType = QStringType; - break; - case QMetaType::QUrl: - regType = QUrlType; - break; - case QMetaType::QColor: - regType = QColorType; - break; - - default: - if (propTy == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) { - regType = PODValueType; - } else if (QDeclarativeMetaType::isQObject(propTy)) { - regType = QObjectStarType; - } else { - if (qmlVerboseCompiler()) - qWarning() << "Discard unsupported property type:" << QMetaType::typeName(propTy); - discard(); // Unsupported type - return; - } - - break; - } // switch - - if (e->property->hasAccessors()) { - Instr::FetchAndSubscribe fetch; - fetch.reg = currentReg; - fetch.subscription = subscriptionIndex(_subscribeName); - fetch.exceptionId = exceptionId(e->line, e->column); - fetch.valueType = regType; - fetch.property = *e->property; - gen(fetch); - } else { - if (blockNeedsSubscription(_subscribeName) && e->property->notifyIndex != -1) { - Instr::Subscribe sub; - sub.reg = currentReg; - sub.offset = subscriptionIndex(_subscribeName); - sub.index = e->property->notifyIndex; - gen(sub); - } - - Instr::Fetch fetch; - fetch.reg = currentReg; - fetch.index = e->property->coreIndex; - fetch.exceptionId = exceptionId(e->line, e->column); - fetch.valueType = regType; - gen(fetch); - } - - } break; - } // switch -} - -void QV4CompilerPrivate::visitTemp(IR::Temp *e) -{ - if (currentReg != e->index) { - Instr::Copy i; - i.reg = currentReg; - i.src = e->index; - gen(i); - } -} - -void QV4CompilerPrivate::visitUnop(IR::Unop *e) -{ - quint8 src = currentReg; - - if (IR::Temp *temp = e->expr->asTemp()) { - src = temp->index; - } else { - traceExpression(e->expr, src); - } - - switch (e->op) { - case IR::OpInvalid: - Q_ASSERT(!"unreachable"); - break; - - case IR::OpIfTrue: - convertToBool(e->expr, src); - if (src != currentReg) { - Instr::Copy i; - i.reg = currentReg; - i.src = src; - gen(i); - } - break; - - case IR::OpNot: { - Instr::UnaryNot i; - convertToBool(e->expr, src); - i.output = currentReg; - i.src = src; - gen(i); - } break; - - case IR::OpUMinus: - if (e->expr->type == IR::RealType) { - Instr::UnaryMinusReal i; - i.output = currentReg; - i.src = src; - gen(i); - } else if (e->expr->type == IR::IntType) { - convertToReal(e->expr, currentReg); - Instr::UnaryMinusReal i; - i.output = currentReg; - i.src = src; - gen(i); - } else { - discard(); - } - break; - - case IR::OpUPlus: - if (e->expr->type == IR::RealType) { - Instr::UnaryPlusReal i; - i.output = currentReg; - i.src = src; - gen(i); - } else if (e->expr->type == IR::IntType) { - convertToReal(e->expr, currentReg); - Instr::UnaryPlusReal i; - i.output = currentReg; - i.src = src; - gen(i); - } else { - discard(); - } - break; - - case IR::OpCompl: - // TODO - discard(); - break; - - case IR::OpBitAnd: - case IR::OpBitOr: - case IR::OpBitXor: - case IR::OpAdd: - case IR::OpSub: - case IR::OpMul: - case IR::OpDiv: - case IR::OpMod: - case IR::OpLShift: - case IR::OpRShift: - case IR::OpURShift: - case IR::OpGt: - case IR::OpLt: - case IR::OpGe: - case IR::OpLe: - case IR::OpEqual: - case IR::OpNotEqual: - case IR::OpStrictEqual: - case IR::OpStrictNotEqual: - case IR::OpAnd: - case IR::OpOr: - Q_ASSERT(!"unreachable"); - break; - } // switch -} - -void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg) -{ - if (expr->type == IR::RealType) - return; - - switch (expr->type) { - case IR::BoolType: { - Instr::ConvertBoolToReal i; - i.output = i.src = reg; - gen(i); - } break; - - case IR::IntType: { - Instr::ConvertIntToReal i; - i.output = i.src = reg; - gen(i); - } break; - - case IR::RealType: - // nothing to do - return; - - default: - discard(); - break; - } // switch -} - -void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg) -{ - if (expr->type == IR::IntType) - return; - - switch (expr->type) { - case IR::BoolType: { - Instr::ConvertBoolToInt i; - i.output = i.src = reg; - gen(i); - } break; - - case IR::IntType: - // nothing to do - return; - - case IR::RealType: { - Instr::ConvertRealToInt i; - i.output = i.src = reg; - gen(i); - } break; - - default: - discard(); - break; - } // switch -} - -void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg) -{ - if (expr->type == IR::BoolType) - return; - - switch (expr->type) { - case IR::BoolType: - // nothing to do - break; - - case IR::IntType: { - Instr::ConvertIntToBool i; - i.output = i.src = reg; - gen(i); - } break; - - case IR::RealType: { - Instr::ConvertRealToBool i; - i.output = i.src = reg; - gen(i); - } return; - - case IR::StringType: { - Instr::ConvertStringToBool i; - i.output = i.src = reg; - gen(i); - } return; - - case IR::ColorType: { - Instr::ConvertColorToBool i; - i.output = i.src = reg; - gen(i); - } return; - - default: - discard(); - break; - } // switch -} - -quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e) -{ - switch (e->op) { - case IR::OpInvalid: - return V4Instr::Noop; - - case IR::OpIfTrue: - case IR::OpNot: - case IR::OpUMinus: - case IR::OpUPlus: - case IR::OpCompl: - return V4Instr::Noop; - - case IR::OpBitAnd: - return V4Instr::BitAndInt; - - case IR::OpBitOr: - return V4Instr::BitOrInt; - - case IR::OpBitXor: - return V4Instr::BitXorInt; - - case IR::OpAdd: - if (e->type == IR::StringType) - return V4Instr::AddString; - return V4Instr::AddReal; - - case IR::OpSub: - return V4Instr::SubReal; - - case IR::OpMul: - return V4Instr::MulReal; - - case IR::OpDiv: - return V4Instr::DivReal; - - case IR::OpMod: - return V4Instr::ModReal; - - case IR::OpLShift: - return V4Instr::LShiftInt; - - case IR::OpRShift: - return V4Instr::RShiftInt; - - case IR::OpURShift: - return V4Instr::URShiftInt; - - case IR::OpGt: - if (e->left->type == IR::StringType) - return V4Instr::GtString; - return V4Instr::GtReal; - - case IR::OpLt: - if (e->left->type == IR::StringType) - return V4Instr::LtString; - return V4Instr::LtReal; - - case IR::OpGe: - if (e->left->type == IR::StringType) - return V4Instr::GeString; - return V4Instr::GeReal; - - case IR::OpLe: - if (e->left->type == IR::StringType) - return V4Instr::LeString; - return V4Instr::LeReal; - - case IR::OpEqual: - if (e->left->type == IR::StringType) - return V4Instr::EqualString; - return V4Instr::EqualReal; - - case IR::OpNotEqual: - if (e->left->type == IR::StringType) - return V4Instr::NotEqualString; - return V4Instr::NotEqualReal; - - case IR::OpStrictEqual: - if (e->left->type == IR::StringType) - return V4Instr::StrictEqualString; - return V4Instr::StrictEqualReal; - - case IR::OpStrictNotEqual: - if (e->left->type == IR::StringType) - return V4Instr::StrictNotEqualString; - return V4Instr::StrictNotEqualReal; - - case IR::OpAnd: - case IR::OpOr: - return V4Instr::Noop; - - } // switch - - return V4Instr::Noop; -} - -void QV4CompilerPrivate::visitBinop(IR::Binop *e) -{ - int left = currentReg; - int right = currentReg + 1; - - if (e->left->asTemp() && e->type != IR::StringType) // Not sure if the e->type != String test is needed - left = e->left->asTemp()->index; - else - traceExpression(e->left, left); - - if (IR::Temp *t = e->right->asTemp()) - right = t->index; - else - traceExpression(e->right, right); - - if (e->left->type != e->right->type) { - if (qmlVerboseCompiler()) - qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op) - << "(`" << IR::binaryOperator(e->left->type) - << "' and `" - << IR::binaryOperator(e->right->type) - << "'"; - discard(); - return; - } - - switch (e->op) { - case IR::OpInvalid: - discard(); - break; - - // unary - case IR::OpIfTrue: - case IR::OpNot: - case IR::OpUMinus: - case IR::OpUPlus: - case IR::OpCompl: - discard(); - break; - - case IR::OpBitAnd: - case IR::OpBitOr: - case IR::OpBitXor: - case IR::OpLShift: - case IR::OpRShift: - case IR::OpURShift: - convertToInt(e->left, left); - convertToInt(e->right, right); - break; - - case IR::OpAdd: - if (e->type != IR::StringType) { - convertToReal(e->left, left); - convertToReal(e->right, right); - } - break; - - case IR::OpSub: - case IR::OpMul: - case IR::OpDiv: - case IR::OpMod: - convertToReal(e->left, left); - convertToReal(e->right, right); - break; - - case IR::OpGt: - case IR::OpLt: - case IR::OpGe: - case IR::OpLe: - case IR::OpEqual: - case IR::OpNotEqual: - case IR::OpStrictEqual: - case IR::OpStrictNotEqual: - if (e->left->type != IR::StringType) { - convertToReal(e->left, left); - convertToReal(e->right, right); - } - break; - - case IR::OpAnd: - case IR::OpOr: - discard(); // ### unreachable - break; - } // switch - - const quint8 opcode = instructionOpcode(e); - if (opcode != V4Instr::Noop) { - V4Instr instr; - instr.binaryop.output = currentReg; - instr.binaryop.left = left; - instr.binaryop.right = right; - gen(static_cast<V4Instr::Type>(opcode), instr); - } -} - -void QV4CompilerPrivate::visitCall(IR::Call *call) -{ - if (IR::Name *name = call->base->asName()) { - IR::Expr *arg = call->onlyArgument(); - if (arg != 0 && arg->type == IR::RealType) { - traceExpression(arg, currentReg); - - switch (name->builtin) { - case IR::NoBuiltinSymbol: - break; - - case IR::MathSinBultinFunction: { - Instr::MathSinReal i; - i.output = i.src = currentReg; - gen(i); - } return; - - case IR::MathCosBultinFunction: { - Instr::MathCosReal i; - i.output = i.src = currentReg; - gen(i); - } return; - - case IR::MathRoundBultinFunction: { - Instr::MathRoundReal i; - i.output = i.src = currentReg; - gen(i); - } return; - - case IR::MathFloorBultinFunction: { - Instr::MathFloorReal i; - i.output = i.src = currentReg; - gen(i); - } return; - - case IR::MathPIBuiltinConstant: - break; - } // switch - } - } - - if (qmlVerboseCompiler()) - qWarning() << "TODO:" << Q_FUNC_INFO << __LINE__; - discard(); -} - - -// -// statements -// -void QV4CompilerPrivate::visitExp(IR::Exp *s) -{ - traceExpression(s->expr, currentReg); -} - -void QV4CompilerPrivate::visitMove(IR::Move *s) -{ - IR::Temp *target = s->target->asTemp(); - Q_ASSERT(target != 0); - - quint8 dest = target->index; - - if (target->type != s->source->type) { - quint8 src = dest; - - if (IR::Temp *t = s->source->asTemp()) - src = t->index; - else - traceExpression(s->source, dest); - - V4Instr::Type opcode = V4Instr::Noop; - IR::Type targetTy = s->target->type; - IR::Type sourceTy = s->source->type; - - if (sourceTy == IR::UrlType) { - switch (targetTy) { - case IR::BoolType: - case IR::StringType: - // nothing to do. V4 will generate optimized - // url-to-xxx conversions. - break; - default: { - // generate a UrlToString conversion and fix - // the type of the source expression. - V4Instr conv; - conv.unaryop.output = V4Instr::ConvertUrlToString; - conv.unaryop.src = src; - gen(opcode, conv); - - sourceTy = IR::StringType; - break; - } - } // switch - } - - if (targetTy == IR::BoolType) { - switch (sourceTy) { - case IR::IntType: opcode = V4Instr::ConvertIntToBool; break; - case IR::RealType: opcode = V4Instr::ConvertRealToBool; break; - case IR::StringType: opcode = V4Instr::ConvertStringToBool; break; - case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break; - case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break; - default: break; - } // switch - } else if (targetTy == IR::IntType) { - switch (sourceTy) { - case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break; - case IR::RealType: { - if (s->isMoveForReturn) - opcode = V4Instr::MathRoundReal; - else - opcode = V4Instr::ConvertRealToInt; - break; - } - case IR::StringType: opcode = V4Instr::ConvertStringToInt; break; - default: break; - } // switch - } else if (targetTy == IR::RealType) { - switch (sourceTy) { - case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break; - case IR::IntType: opcode = V4Instr::ConvertIntToReal; break; - case IR::StringType: opcode = V4Instr::ConvertStringToReal; break; - default: break; - } // switch - } else if (targetTy == IR::StringType) { - switch (sourceTy) { - case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break; - case IR::IntType: opcode = V4Instr::ConvertIntToString; break; - case IR::RealType: opcode = V4Instr::ConvertRealToString; break; - case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break; - case IR::ColorType: opcode = V4Instr::ConvertColorToString; break; - default: break; - } // switch - } else if (targetTy == IR::UrlType) { - V4Instr convToString; - convToString.unaryop.output = dest; - convToString.unaryop.src = src; - - // try to convert the source expression to a string. - switch (sourceTy) { - case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break; - case IR::IntType: gen(V4Instr::ConvertIntToString, convToString); sourceTy = IR::StringType; break; - case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break; - case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break; - default: break; - } // switch - - if (sourceTy == IR::StringType) - opcode = V4Instr::ConvertStringToUrl; - } else if (targetTy == IR::ColorType) { - switch (sourceTy) { - case IR::StringType: opcode = V4Instr::ConvertStringToColor; break; - default: break; - } // switch - } - if (opcode != V4Instr::Noop) { - V4Instr conv; - conv.unaryop.output = dest; - conv.unaryop.src = src; - gen(opcode, conv); - - if (s->isMoveForReturn && opcode == V4Instr::ConvertStringToUrl) { - V4Instr resolveUrl; - resolveUrl.unaryop.output = dest; - resolveUrl.unaryop.src = dest; - gen(V4Instr::ResolveUrl, resolveUrl); - } - } else { - discard(); - } - } else { - traceExpression(s->source, dest); - } -} - -void QV4CompilerPrivate::visitJump(IR::Jump *s) -{ - patches.append(Patch(s->target, bytecode.size())); - - Instr::Branch i; - i.offset = 0; // ### backpatch - gen(i); -} - -void QV4CompilerPrivate::visitCJump(IR::CJump *s) -{ - traceExpression(s->cond, currentReg); - - patches.append(Patch(s->iftrue, bytecode.size())); - - Instr::BranchTrue i; - i.reg = currentReg; - i.offset = 0; // ### backpatch - gen(i); -} - -void QV4CompilerPrivate::visitRet(IR::Ret *s) -{ - Q_ASSERT(s->expr != 0); - - int storeReg = currentReg; - - if (IR::Temp *temp = s->expr->asTemp()) { - storeReg = temp->index; - } else { - traceExpression(s->expr, storeReg); - } - - if (qmlBindingsTest) { - Instr::TestV4Store test; - test.reg = storeReg; - switch (s->type) { - case IR::StringType: - test.regType = QMetaType::QString; - break; - case IR::UrlType: - test.regType = QMetaType::QUrl; - break; - case IR::ColorType: - test.regType = QMetaType::QColor; - break; - case IR::SGAnchorLineType: - test.regType = QDeclarativeMetaType::QQuickAnchorLineMetaTypeId(); - break; - case IR::ObjectType: - test.regType = QMetaType::QObjectStar; - break; - case IR::BoolType: - test.regType = QMetaType::Bool; - break; - case IR::IntType: - test.regType = QMetaType::Int; - break; - case IR::RealType: - test.regType = QMetaType::QReal; - break; - default: - discard(); - return; - } - gen(test); - } - - Instr::Store store; - store.output = 0; - store.index = expression->property->index; - store.reg = storeReg; - store.exceptionId = exceptionId(s->line, s->column); - gen(store); -} - -void QV4Compiler::dump(const QByteArray &programData) -{ - const QV4Program *program = (const QV4Program *)programData.constData(); - - qWarning() << "Program.bindings:" << program->bindings; - qWarning() << "Program.dataLength:" << program->dataLength; - qWarning() << "Program.subscriptions:" << program->subscriptions; - qWarning() << "Program.indentifiers:" << program->identifiers; - - const int programSize = program->instructionCount; - const char *start = program->instructions(); - const char *end = start + programSize; - Bytecode bc; - bc.dump(start, end); -} - -/*! -Clear the state associated with attempting to compile a specific binding. -This does not clear the global "committed binding" states. -*/ -void QV4CompilerPrivate::resetInstanceState() -{ - data = committed.data; - exceptions = committed.exceptions; - usedSubscriptionIds.clear(); - subscriptionIds = committed.subscriptionIds; - registeredStrings = committed.registeredStrings; - bytecode.clear(); - patches.clear(); - pool.clear(); - currentReg = 0; -} - -/*! -Mark the last compile as successful, and add it to the "committed data" -section. - -Returns the index for the committed binding. -*/ -int QV4CompilerPrivate::commitCompile() -{ - int rv = committed.count(); - committed.offsets << committed.bytecode.count(); - committed.dependencies << usedSubscriptionIds; - committed.bytecode.append(bytecode.constData(), bytecode.size()); - committed.data = data; - committed.exceptions = exceptions; - committed.subscriptionIds = subscriptionIds; - committed.registeredStrings = registeredStrings; - return rv; -} - -bool QV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node) -{ - resetInstanceState(); - - if (expression->property->type == -1) - return false; - - AST::SourceLocation location; - if (AST::ExpressionNode *astExpression = node->expressionCast()) { - location = astExpression->firstSourceLocation(); - } else if (AST::Statement *astStatement = node->statementCast()) { - if (AST::Block *block = AST::cast<AST::Block *>(astStatement)) - location = block->lbraceToken; - else if (AST::IfStatement *ifStmt = AST::cast<AST::IfStatement *>(astStatement)) - location = ifStmt->ifToken; - else - return false; - } else { - return false; - } - - IR::Function thisFunction(&pool), *function = &thisFunction; - - QV4IRBuilder irBuilder(expression, engine); - if (!irBuilder(function, node)) - return false; - - bool discarded = false; - qSwap(_discarded, discarded); - qSwap(_function, function); - trace(location.startLine, location.startColumn); - qSwap(_function, function); - qSwap(_discarded, discarded); - - if (qmlVerboseCompiler()) { - QTextStream qerr(stderr, QIODevice::WriteOnly); - if (discarded) - qerr << "======== TODO ====== " << endl; - else - qerr << "==================== " << endl; - qerr << "\tline: " << location.startLine - << "\tcolumn: " << location.startColumn - << endl; - foreach (IR::BasicBlock *bb, function->basicBlocks) - bb->dump(qerr); - qerr << endl; - } - - if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31) - return false; - - return true; -} - -// Returns a reg -int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str) -{ - // ### string cleanup - - QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); - int offset = data.count(); - data += strdata; - - Instr::LoadString string; - string.reg = reg; - string.offset = offset; - string.length = str.length(); - gen(string); - - return reg; -} - -// Returns an identifier offset -int QV4CompilerPrivate::registerString(const QString &string) -{ - Q_ASSERT(!string.isEmpty()); - - QPair<int, int> *iter = registeredStrings.value(string); - - if (!iter) { - quint32 len = string.length(); - QByteArray lendata((const char *)&len, sizeof(quint32)); - QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar)); - strdata.prepend(lendata); - int rv = data.count(); - data += strdata; - - iter = ®isteredStrings[string]; - *iter = qMakePair(registeredStrings.count(), rv); - } - - Instr::InitString reg; - reg.offset = iter->first; - reg.dataIdx = iter->second; - gen(reg); - return reg.offset; -} - -/*! -Returns true if the current expression has not already subscribed to \a sub in currentBlockMask. -*/ -bool QV4CompilerPrivate::blockNeedsSubscription(const QStringList &sub) -{ - QString str = sub.join(QLatin1String(".")); - - int *iter = subscriptionIds.value(str); - if (!iter) - return true; - - quint32 *uiter = usedSubscriptionIds.value(*iter); - if (!uiter) - return true; - else - return !(*uiter & currentBlockMask); -} - -int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub) -{ - QString str = sub.join(QLatin1String(".")); - int *iter = subscriptionIds.value(str); - if (!iter) { - int count = subscriptionIds.count(); - iter = &subscriptionIds[str]; - *iter = count; - } - quint32 &u = usedSubscriptionIds[*iter]; - if (!(u & currentBlockMask)) { - u |= currentBlockMask; - usedSubscriptionIdsChanged = true; - } - return *iter; -} - -quint32 QV4CompilerPrivate::subscriptionBlockMask(const QStringList &sub) -{ - QString str = sub.join(QLatin1String(".")); - - int *iter = subscriptionIds.value(str); - Q_ASSERT(iter != 0); - - quint32 *uiter = usedSubscriptionIds.value(*iter); - Q_ASSERT(uiter != 0); - - return *uiter; -} - -quint8 QV4CompilerPrivate::exceptionId(quint32 line, quint32 column) -{ - quint8 rv = 0xFF; - if (exceptions.count() < 0xFF) { - rv = (quint8)exceptions.count(); - quint64 e = line; - e <<= 32; - e |= column; - exceptions.append(e); - } - return rv; -} - -quint8 QV4CompilerPrivate::exceptionId(QDeclarativeJS::AST::ExpressionNode *n) -{ - quint8 rv = 0xFF; - if (n && exceptions.count() < 0xFF) { - QDeclarativeJS::AST::SourceLocation l = n->firstSourceLocation(); - rv = exceptionId(l.startLine, l.startColumn); - } - return rv; -} - -QV4Compiler::QV4Compiler() -: d(new QV4CompilerPrivate) -{ - qmlBindingsTest |= qmlBindingsTestEnv(); -} - -QV4Compiler::~QV4Compiler() -{ - delete d; d = 0; -} - -/* -Returns true if any bindings were compiled. -*/ -bool QV4Compiler::isValid() const -{ - return !d->committed.bytecode.isEmpty(); -} - -/* --1 on failure, otherwise the binding index to use. -*/ -int QV4Compiler::compile(const Expression &expression, QDeclarativeEnginePrivate *engine) -{ - if (!expression.expression.asAST()) return false; - - if (!qmlExperimental() && expression.property->isValueTypeSubProperty) - return -1; - - if (qmlDisableOptimizer() || !qmlEnableV4) - return -1; - - d->expression = &expression; - d->engine = engine; - - if (d->compile(expression.expression.asAST())) { - return d->commitCompile(); - } else { - return -1; - } -} - -QByteArray QV4CompilerPrivate::buildSignalTable() const -{ - QHash<int, QList<QPair<int, quint32> > > table; - - for (int ii = 0; ii < committed.count(); ++ii) { - const QDeclarativeAssociationList<int, quint32> &deps = committed.dependencies.at(ii); - for (QDeclarativeAssociationList<int, quint32>::const_iterator iter = deps.begin(); iter != deps.end(); ++iter) - table[iter->first].append(qMakePair(ii, iter->second)); - } - - QVector<quint32> header; - QVector<quint32> data; - for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) { - header.append(committed.subscriptionIds.count() + data.count()); - const QList<QPair<int, quint32> > &bindings = table[ii]; - data.append(bindings.count()); - for (int jj = 0; jj < bindings.count(); ++jj) { - data.append(bindings.at(jj).first); - data.append(bindings.at(jj).second); - } - } - header << data; - - return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32)); -} - -QByteArray QV4CompilerPrivate::buildExceptionData() const -{ - QByteArray rv; - rv.resize(committed.exceptions.count() * sizeof(quint64)); - ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); - return rv; -} - -/* -Returns the compiled program. -*/ -QByteArray QV4Compiler::program() const -{ - QByteArray programData; - - if (isValid()) { - QV4Program prog; - prog.bindings = d->committed.count(); - - Bytecode bc; - QV4CompilerPrivate::Instr::Jump jump; - jump.reg = -1; - - for (int ii = 0; ii < d->committed.count(); ++ii) { - jump.count = d->committed.count() - ii - 1; - jump.count*= V4InstrMeta<V4Instr::Jump>::Size; - jump.count+= d->committed.offsets.at(ii); - bc.append(jump); - } - - - QByteArray bytecode; - bytecode.reserve(bc.size() + d->committed.bytecode.size()); - bytecode.append(bc.constData(), bc.size()); - bytecode.append(d->committed.bytecode.constData(), d->committed.bytecode.size()); - - QByteArray data = d->committed.data; - while (data.count() % 4) data.append('\0'); - prog.signalTableOffset = data.count(); - data += d->buildSignalTable(); - while (data.count() % 4) data.append('\0'); - prog.exceptionDataOffset = data.count(); - data += d->buildExceptionData(); - - prog.dataLength = 4 * ((data.size() + 3) / 4); - prog.subscriptions = d->committed.subscriptionIds.count(); - prog.identifiers = d->committed.registeredStrings.count(); - prog.instructionCount = bytecode.count(); - int size = sizeof(QV4Program) + bytecode.count(); - size += prog.dataLength; - - programData.resize(size); - memcpy(programData.data(), &prog, sizeof(QV4Program)); - if (prog.dataLength) - memcpy((char *)((QV4Program *)programData.data())->data(), data.constData(), - data.size()); - memcpy((char *)((QV4Program *)programData.data())->instructions(), bytecode.constData(), - bytecode.count()); - } - - if (bindingsDump()) { - qWarning().nospace() << "Subscription slots:"; - - for (QDeclarativeAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin(); - iter != d->committed.subscriptionIds.end(); - ++iter) { - qWarning().nospace() << " " << iter->first << "\t-> " << iter->second; - } - - QV4Compiler::dump(programData); - } - - return programData; -} - -void QV4Compiler::enableBindingsTest(bool e) -{ - if (e) - qmlBindingsTest = true; - else - qmlBindingsTest = qmlBindingsTestEnv(); -} - -void QV4Compiler::enableV4(bool e) -{ - qmlEnableV4 = e; -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qv4compiler_p.h b/src/declarative/qml/v4/qv4compiler_p.h deleted file mode 100644 index 99d5569b6a..0000000000 --- a/src/declarative/qml/v4/qv4compiler_p.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4COMPILER_P_H -#define QV4COMPILER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qdeclarativeexpression_p.h> -#include <private/qdeclarativebinding_p.h> -#include <private/qdeclarativecompiler_p.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QDeclarativeTypeNameCache; -class QV4CompilerPrivate; -class Q_AUTOTEST_EXPORT QV4Compiler -{ -public: - QV4Compiler(); - ~QV4Compiler(); - - // Returns true if bindings were compiled - bool isValid() const; - - struct Expression - { - Expression(const QDeclarativeImports &imp) : imports(imp) {} - QDeclarativeScript::Object *component; - QDeclarativeScript::Object *context; - QDeclarativeScript::Property *property; - QDeclarativeScript::Variant expression; - QDeclarativeCompilerTypes::IdList *ids; - QDeclarativeTypeNameCache *importCache; - QDeclarativeImports imports; - }; - - // -1 on failure, otherwise the binding index to use - int compile(const Expression &, QDeclarativeEnginePrivate *); - - // Returns the compiled program - QByteArray program() const; - - static void dump(const QByteArray &); - static void enableBindingsTest(bool); - static void enableV4(bool); -private: - QV4CompilerPrivate *d; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4COMPILER_P_H - diff --git a/src/declarative/qml/v4/qv4compiler_p_p.h b/src/declarative/qml/v4/qv4compiler_p_p.h deleted file mode 100644 index c43140663e..0000000000 --- a/src/declarative/qml/v4/qv4compiler_p_p.h +++ /dev/null @@ -1,246 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4COMPILER_P_P_H -#define QV4COMPILER_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qv4instruction_p.h" -#include "qv4ir_p.h" -#include <private/qdeclarativescript_p.h> -#include <private/qdeclarativeimport_p.h> -#include <private/qdeclarativeengine_p.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -template <typename _Key, typename _Value> -class QDeclarativeAssociationList -{ -public: - typedef QVarLengthArray<QPair<_Key, _Value>, 8> Container; - typedef typename Container::const_iterator const_iterator; - typedef typename Container::const_iterator ConstIterator; - - const_iterator begin() const { return _container.begin(); } - const_iterator end() const { return _container.end(); } - int count() const { return _container.count(); } - void clear() { _container.clear(); } - - _Value *value(const _Key &key) { - for (int i = 0; i < _container.size(); ++i) { - QPair<_Key, _Value> &p = _container[i]; - if (p.first == key) - return &p.second; - } - return 0; - } - - _Value &operator[](const _Key &key) { - for (int i = 0; i < _container.size(); ++i) { - QPair<_Key, _Value> &p = _container[i]; - if (p.first == key) - return p.second; - } - int index = _container.size(); - _container.append(qMakePair(key, _Value())); - return _container[index].second; - } - - void insert(const _Key &key, _Value &value) { - for (int i = 0; i < _container.size(); ++i) { - QPair<_Key, _Value> &p = _container[i]; - if (p.first == key) { - p.second = value; - return; - } - } - _container.append(qMakePair(key, value)); - } - -private: - Container _container; -}; - -class QV4CompilerPrivate: protected QDeclarativeJS::IR::ExprVisitor, - protected QDeclarativeJS::IR::StmtVisitor -{ -public: - QV4CompilerPrivate(); - - void resetInstanceState(); - int commitCompile(); - - const QV4Compiler::Expression *expression; - QDeclarativeEnginePrivate *engine; - - QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)expression->context, 16); } - - bool compile(QDeclarativeJS::AST::Node *); - - int registerLiteralString(quint8 reg, const QStringRef &); - int registerString(const QString &); - QDeclarativeAssociationList<QString, QPair<int, int> > registeredStrings; - QByteArray data; - - bool blockNeedsSubscription(const QStringList &); - int subscriptionIndex(const QStringList &); - quint32 subscriptionBlockMask(const QStringList &); - - quint8 exceptionId(quint32 line, quint32 column); - quint8 exceptionId(QDeclarativeJS::AST::ExpressionNode *); - QVector<quint64> exceptions; - - QDeclarativeAssociationList<int, quint32> usedSubscriptionIds; - - QDeclarativeAssociationList<QString, int> subscriptionIds; - QDeclarativeJS::Bytecode bytecode; - - // back patching - struct Patch { - QDeclarativeJS::IR::BasicBlock *block; // the basic block - int offset; // the index of the instruction to patch - Patch(QDeclarativeJS::IR::BasicBlock *block = 0, int index = -1) - : block(block), offset(index) {} - }; - QVector<Patch> patches; - QDeclarativePool pool; - - // Committed binding data - struct { - QList<int> offsets; - QList<QDeclarativeAssociationList<int, quint32> > dependencies; - - //QDeclarativeJS::Bytecode bytecode; - QByteArray bytecode; - QByteArray data; - QDeclarativeAssociationList<QString, int> subscriptionIds; - QVector<quint64> exceptions; - - QDeclarativeAssociationList<QString, QPair<int, int> > registeredStrings; - - int count() const { return offsets.count(); } - } committed; - - QByteArray buildSignalTable() const; - QByteArray buildExceptionData() const; - - void convertToReal(QDeclarativeJS::IR::Expr *expr, int reg); - void convertToInt(QDeclarativeJS::IR::Expr *expr, int reg); - void convertToBool(QDeclarativeJS::IR::Expr *expr, int reg); - quint8 instructionOpcode(QDeclarativeJS::IR::Binop *e); - - struct Instr { -#define QML_V4_INSTR_DATA_TYPEDEF(I, FMT) typedef QDeclarativeJS::V4InstrData<QDeclarativeJS::V4Instr::I> I; - FOR_EACH_V4_INSTR(QML_V4_INSTR_DATA_TYPEDEF) -#undef QML_v4_INSTR_DATA_TYPEDEF - private: - Instr(); - }; - -protected: - // - // tracing - // - void trace(int line, int column); - void trace(QVector<QDeclarativeJS::IR::BasicBlock *> *blocks); - void traceExpression(QDeclarativeJS::IR::Expr *e, quint8 r); - - template <int Instr> - inline void gen(const QDeclarativeJS::V4InstrData<Instr> &i) - { bytecode.append(i); } - inline void gen(QDeclarativeJS::V4Instr::Type type, QDeclarativeJS::V4Instr &instr) - { bytecode.append(type, instr); } - - inline QDeclarativeJS::V4Instr::Type instructionType(const QDeclarativeJS::V4Instr *i) const - { return bytecode.instructionType(i); } - - // - // expressions - // - virtual void visitConst(QDeclarativeJS::IR::Const *e); - virtual void visitString(QDeclarativeJS::IR::String *e); - virtual void visitName(QDeclarativeJS::IR::Name *e); - virtual void visitTemp(QDeclarativeJS::IR::Temp *e); - virtual void visitUnop(QDeclarativeJS::IR::Unop *e); - virtual void visitBinop(QDeclarativeJS::IR::Binop *e); - virtual void visitCall(QDeclarativeJS::IR::Call *e); - - // - // statements - // - virtual void visitExp(QDeclarativeJS::IR::Exp *s); - virtual void visitMove(QDeclarativeJS::IR::Move *s); - virtual void visitJump(QDeclarativeJS::IR::Jump *s); - virtual void visitCJump(QDeclarativeJS::IR::CJump *s); - virtual void visitRet(QDeclarativeJS::IR::Ret *s); - -private: - QStringList _subscribeName; - QDeclarativeJS::IR::Function *_function; - QDeclarativeJS::IR::BasicBlock *_block; - void discard() { _discarded = true; } - bool _discarded; - quint8 currentReg; - quint8 registerCount; - - bool usedSubscriptionIdsChanged; - quint32 currentBlockMask; -}; - - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4COMPILER_P_P_H - diff --git a/src/declarative/qml/v4/qv4instruction.cpp b/src/declarative/qml/v4/qv4instruction.cpp deleted file mode 100644 index e9213f5e3f..0000000000 --- a/src/declarative/qml/v4/qv4instruction.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4instruction_p.h" -#include "qv4bindings_p.h" - -#include <QtCore/qdebug.h> -#include <private/qdeclarativeglobal_p.h> - -// Define this to do a test dump of all the instructions at startup. This is -// helpful to test that each instruction's Instr::dump() case uses the correct -// number of tabs etc and otherwise looks correct. -// #define DEBUG_INSTR_DUMP - -QT_BEGIN_NAMESPACE - -namespace QDeclarativeJS { - -#ifdef DEBUG_INSTR_DUMP -static struct DumpInstrAtStartup { - DumpInstrAtStartup() { - Bytecode bc; -#define DUMP_INSTR_AT_STARTUP(I, FMT) { V4InstrData<V4Instr::I> i; bc.append(i); } - FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP); -#undef DUMP_INSTR_AT_STARTUP - const char *start = bc.constData(); - const char *end = start + bc.size(); - bc.dump(start, end); - } -} dump_instr_at_startup; -#endif - -int V4Instr::size(Type type) -{ -#define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT); - switch (type) { - FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE) - } -#undef V4_RETURN_INSTR_SIZE - return 0; -} - -void Bytecode::dump(const V4Instr *i, int address) const -{ - QByteArray leading; - if (address != -1) { - leading = QByteArray::number(address); - leading.prepend(QByteArray(8 - leading.count(), ' ')); - leading.append("\t"); - } - -#define INSTR_DUMP qWarning().nospace() << leading.constData() - - switch (instructionType(i)) { - case V4Instr::Noop: - INSTR_DUMP << "\t" << "Noop"; - break; - case V4Instr::BindingId: - INSTR_DUMP << i->id.line << ":" << i->id.column << ":"; - break; - case V4Instr::Subscribe: - INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << i->subscribeop.reg << ") Notify_Signal(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")"; - break; - case V4Instr::SubscribeId: - INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")"; - break; - case V4Instr::FetchAndSubscribe: - INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.property.accessors << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" << i->fetchAndSubscribe.subscription << ")"; - break; - case V4Instr::LoadId: - INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")"; - break; - case V4Instr::LoadScope: - INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")"; - break; - case V4Instr::LoadRoot: - INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")"; - break; - case V4Instr::LoadAttached: - INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")"; - break; - case V4Instr::UnaryNot: - INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::UnaryMinusReal: - INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::UnaryMinusInt: - INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::UnaryPlusReal: - INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::UnaryPlusInt: - INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertBoolToInt: - INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertBoolToReal: - INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertBoolToString: - INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertIntToBool: - INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertIntToReal: - INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertIntToString: - INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertRealToBool: - INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertRealToInt: - INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertRealToString: - INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertStringToBool: - INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertStringToInt: - INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertStringToReal: - INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertStringToUrl: - INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertStringToColor: - INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertUrlToBool: - INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertUrlToString: - INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertColorToBool: - INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ConvertColorToString: - INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::ResolveUrl: - INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::MathSinReal: - INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::MathCosReal: - INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::MathRoundReal: - INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::MathFloorReal: - INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::MathPIReal: - INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; - break; - case V4Instr::LoadReal: - INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")"; - break; - case V4Instr::LoadInt: - INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")"; - break; - case V4Instr::LoadBool: - INSTR_DUMP << "\t" << "LoadBool" << "\t\t" << "Constant(" << i->bool_value.value << ") -> Output_Reg(" << i->bool_value.reg << ")"; - break; - case V4Instr::LoadString: - INSTR_DUMP << "\t" << "LoadString" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ") -> Output_Register(" << i->string_value.reg << ")"; - break; - case V4Instr::EnableV4Test: - INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ")"; - break; - case V4Instr::TestV4Store: - INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << i->storetest.reg << ") Reg_Type(" << i->storetest.regType << ")"; - break; - case V4Instr::BitAndInt: - INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::BitOrInt: - INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::BitXorInt: - INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::AddReal: - INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::AddString: - INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::SubReal: - INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::MulReal: - INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::DivReal: - INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::ModReal: - INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::LShiftInt: - INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::RShiftInt: - INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::URShiftInt: - INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::GtReal: - INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::LtReal: - INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::GeReal: - INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::LeReal: - INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::EqualReal: - INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::NotEqualReal: - INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::StrictEqualReal: - INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::StrictNotEqualReal: - INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::GtString: - INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::LtString: - INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::GeString: - INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::LeString: - INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::EqualString: - INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::NotEqualString: - INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::StrictEqualString: - INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::StrictNotEqualString: - INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; - break; - case V4Instr::NewString: - INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")"; - break; - case V4Instr::NewUrl: - INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << i->construct.reg << ")"; - break; - case V4Instr::CleanupRegister: - INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << i->cleanup.reg << ")"; - break; - case V4Instr::Fetch: - INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << i->fetch.reg << ") Property_Index(" << i->fetch.index << ") -> Output_Reg(" << i->fetch.reg << ")"; - break; - case V4Instr::Store: - INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << i->store.reg << ") -> Object_Reg(" << i->store.output << ") Property_Index(" << i->store.index << ")"; - break; - case V4Instr::Copy: - INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << i->copy.src << ") -> Output_Reg(" << i->copy.reg << ")"; - break; - case V4Instr::Jump: - if (i->jump.reg != -1) { - INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ") [if false == Input_Reg(" << i->jump.reg << ")]"; - } else { - INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ")"; - } - break; - case V4Instr::BranchFalse: - INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if false == Input_Reg(" << i->branchop.reg << ")]"; - break; - case V4Instr::BranchTrue: - INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if true == Input_Reg(" << i->branchop.reg << ")]"; - break; - case V4Instr::Branch: - INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")"; - break; - case V4Instr::InitString: - INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")"; - break; - case V4Instr::Block: - INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")"; - break; - default: - INSTR_DUMP << "\t" << "Unknown"; - break; - } -} - -void Bytecode::dump(const char *start, const char *end) const -{ - const char *code = start; - while (code < end) { - const V4Instr *instr = reinterpret_cast<const V4Instr *>(code); - dump(instr, code - start); - code += V4Instr::size(instructionType(instr)); - } -} - -Bytecode::Bytecode() -{ -#ifdef QML_THREADED_INTERPRETER - decodeInstr = QV4Bindings::getDecodeInstrTable(); -#endif -} - -V4Instr::Type Bytecode::instructionType(const V4Instr *instr) const -{ -#ifdef QML_THREADED_INTERPRETER - void *code = instr->common.code; - -# define CHECK_V4_INSTR_CODE(I, FMT) \ - if (decodeInstr[static_cast<int>(V4Instr::I)] == code) \ - return V4Instr::I; - - FOR_EACH_V4_INSTR(CHECK_V4_INSTR_CODE) - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address"); - return static_cast<V4Instr::Type>(0); -# undef CHECK_V4_INSTR_CODE -#else - return static_cast<V4Instr::Type>(instr->common.type); -#endif - -} - -void Bytecode::append(V4Instr::Type type, V4Instr &instr) -{ -#ifdef QML_THREADED_INTERPRETER - instr.common.code = decodeInstr[static_cast<int>(type)]; -#else - instr.common.type = type; -#endif - d.append(reinterpret_cast<const char *>(&instr), V4Instr::size(type)); -} - -int Bytecode::remove(int offset) -{ - const V4Instr *instr = reinterpret_cast<const V4Instr *>(d.begin() + offset); - const int instrSize = V4Instr::size(instructionType(instr)); - d.remove(offset, instrSize); - return instrSize; -} - -const V4Instr &Bytecode::operator[](int offset) const -{ - return *(reinterpret_cast<const V4Instr *>(d.begin() + offset)); -} - -V4Instr &Bytecode::operator[](int offset) -{ - return *(reinterpret_cast<V4Instr *>(d.begin() + offset)); -} - -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qv4instruction_p.h b/src/declarative/qml/v4/qv4instruction_p.h deleted file mode 100644 index d243d3fb9d..0000000000 --- a/src/declarative/qml/v4/qv4instruction_p.h +++ /dev/null @@ -1,435 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4INSTRUCTION_P_H -#define QV4INSTRUCTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qbytearray.h> -#include <QtCore/qvector.h> -#include <QtCore/qvarlengtharray.h> - -#include <private/qdeclarativepropertycache_p.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -#define FOR_EACH_V4_INSTR(F) \ - F(Noop, common) \ - F(BindingId, id) \ - F(Subscribe, subscribeop) \ - F(SubscribeId, subscribeop) \ - F(FetchAndSubscribe, fetchAndSubscribe) \ - F(LoadId, load) \ - F(LoadScope, load) \ - F(LoadRoot, load) \ - F(LoadAttached, attached) \ - F(UnaryNot, unaryop) \ - F(UnaryMinusReal, unaryop) \ - F(UnaryMinusInt, unaryop) \ - F(UnaryPlusReal, unaryop) \ - F(UnaryPlusInt, unaryop) \ - F(ConvertBoolToInt, unaryop) \ - F(ConvertBoolToReal, unaryop) \ - F(ConvertBoolToString, unaryop) \ - F(ConvertIntToBool, unaryop) \ - F(ConvertIntToReal, unaryop) \ - F(ConvertIntToString, unaryop) \ - F(ConvertRealToBool, unaryop) \ - F(ConvertRealToInt, unaryop) \ - F(ConvertRealToString, unaryop) \ - F(ConvertStringToBool, unaryop) \ - F(ConvertStringToInt, unaryop) \ - F(ConvertStringToReal, unaryop) \ - F(ConvertStringToUrl, unaryop) \ - F(ConvertStringToColor, unaryop) \ - F(ConvertUrlToBool, unaryop) \ - F(ConvertUrlToString, unaryop) \ - F(ConvertColorToBool, unaryop) \ - F(ConvertColorToString, unaryop) \ - F(ResolveUrl, unaryop) \ - F(MathSinReal, unaryop) \ - F(MathCosReal, unaryop) \ - F(MathRoundReal, unaryop) \ - F(MathFloorReal, unaryop) \ - F(MathPIReal, unaryop) \ - F(LoadReal, real_value) \ - F(LoadInt, int_value) \ - F(LoadBool, bool_value) \ - F(LoadString, string_value) \ - F(EnableV4Test, string_value) \ - F(TestV4Store, storetest) \ - F(BitAndInt, binaryop) \ - F(BitOrInt, binaryop) \ - F(BitXorInt, binaryop) \ - F(AddReal, binaryop) \ - F(AddString, binaryop) \ - F(SubReal, binaryop) \ - F(MulReal, binaryop) \ - F(DivReal, binaryop) \ - F(ModReal, binaryop) \ - F(LShiftInt, binaryop) \ - F(RShiftInt, binaryop) \ - F(URShiftInt, binaryop) \ - F(GtReal, binaryop) \ - F(LtReal, binaryop) \ - F(GeReal, binaryop) \ - F(LeReal, binaryop) \ - F(EqualReal, binaryop) \ - F(NotEqualReal, binaryop) \ - F(StrictEqualReal, binaryop) \ - F(StrictNotEqualReal, binaryop) \ - F(GtString, binaryop) \ - F(LtString, binaryop) \ - F(GeString, binaryop) \ - F(LeString, binaryop) \ - F(EqualString, binaryop) \ - F(NotEqualString, binaryop) \ - F(StrictEqualString, binaryop) \ - F(StrictNotEqualString, binaryop) \ - F(NewString, construct) \ - F(NewUrl, construct) \ - F(CleanupRegister, cleanup) \ - F(Copy, copy) \ - F(Fetch, fetch) \ - F(Store, store) \ - F(Jump, jump) \ - F(BranchTrue, branchop) \ - F(BranchFalse, branchop) \ - F(Branch, branchop) \ - F(Block, blockop) \ - /* Speculative property resolution */ \ - F(InitString, initstring) - -#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) -# define QML_THREADED_INTERPRETER -#endif - -#ifdef Q_ALIGNOF -# define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(V4Instr) - 1) -#else -# define QML_V4_INSTR_ALIGN_MASK (sizeof(void *) - 1) -#endif - -#define QML_V4_INSTR_ENUM(I, FMT) I, -#define QML_V4_INSTR_ADDR(I, FMT) &&op_##I, -#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(V4Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK) - -#ifdef QML_THREADED_INTERPRETER -# define QML_V4_BEGIN_INSTR(I,FMT) op_##I: -# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; goto *instr->common.code; -# define QML_V4_INSTR_HEADER void *code; -#else -# define QML_V4_BEGIN_INSTR(I,FMT) case V4Instr::I: -# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; break; -# define QML_V4_INSTR_HEADER quint8 type; -#endif - -class QObject; -class QDeclarativeNotifier; - -namespace QDeclarativeJS { - -union V4Instr { - enum Type { - FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM) - }; - - static int size(Type type); - - struct instr_common { - QML_V4_INSTR_HEADER - }; - - struct instr_id { - QML_V4_INSTR_HEADER - quint16 column; - quint32 line; - }; - - struct instr_init { - QML_V4_INSTR_HEADER - quint16 subscriptions; - quint16 identifiers; - }; - - struct instr_subscribeop { - QML_V4_INSTR_HEADER - qint8 reg; - quint16 offset; - quint32 index; - }; - - struct instr_load { - QML_V4_INSTR_HEADER - qint8 reg; - quint32 index; - }; - - struct instr_attached { - QML_V4_INSTR_HEADER - qint8 output; - qint8 reg; - quint8 exceptionId; - quint32 id; - }; - - struct instr_store { - QML_V4_INSTR_HEADER - qint8 output; - qint8 reg; - quint8 exceptionId; - quint32 index; - }; - - struct instr_storetest { - QML_V4_INSTR_HEADER - qint8 reg; - qint32 regType; - }; - - struct instr_fetchAndSubscribe { - QML_V4_INSTR_HEADER - qint8 reg; - quint8 exceptionId; - quint8 valueType; - quint16 subscription; - QDeclarativePropertyRawData property; - }; - - struct instr_fetch{ - QML_V4_INSTR_HEADER - qint8 reg; - quint8 exceptionId; - quint8 valueType; - quint32 index; - }; - - struct instr_copy { - QML_V4_INSTR_HEADER - qint8 reg; - qint8 src; - }; - - struct instr_construct { - QML_V4_INSTR_HEADER - qint8 reg; - }; - - struct instr_real_value { - QML_V4_INSTR_HEADER - qint8 reg; - qreal value; // XXX Makes the instruction 12 bytes - }; - - struct instr_int_value { - QML_V4_INSTR_HEADER - qint8 reg; - int value; - }; - - struct instr_bool_value { - QML_V4_INSTR_HEADER - qint8 reg; - bool value; - }; - - struct instr_string_value { - QML_V4_INSTR_HEADER - qint8 reg; - quint16 length; - quint32 offset; - }; - - struct instr_binaryop { - QML_V4_INSTR_HEADER - qint8 output; - qint8 left; - qint8 right; - }; - - struct instr_unaryop { - QML_V4_INSTR_HEADER - qint8 output; - qint8 src; - }; - - struct instr_jump { - QML_V4_INSTR_HEADER - qint8 reg; - quint32 count; - }; - - struct instr_find { - QML_V4_INSTR_HEADER - qint8 reg; - qint8 src; - quint8 exceptionId; - quint16 name; - quint16 subscribeIndex; - }; - - struct instr_cleanup { - QML_V4_INSTR_HEADER - qint8 reg; - }; - - struct instr_initstring { - QML_V4_INSTR_HEADER - quint16 offset; - quint32 dataIdx; - }; - - struct instr_branchop { - QML_V4_INSTR_HEADER - quint8 reg; - qint16 offset; - }; - - struct instr_blockop { - QML_V4_INSTR_HEADER - quint32 block; - }; - - instr_common common; - instr_id id; - instr_init init; - instr_subscribeop subscribeop; - instr_load load; - instr_attached attached; - instr_store store; - instr_storetest storetest; - instr_fetchAndSubscribe fetchAndSubscribe; - instr_fetch fetch; - instr_copy copy; - instr_construct construct; - instr_real_value real_value; - instr_int_value int_value; - instr_bool_value bool_value; - instr_string_value string_value; - instr_binaryop binaryop; - instr_unaryop unaryop; - instr_jump jump; - instr_find find; - instr_cleanup cleanup; - instr_initstring initstring; - instr_branchop branchop; - instr_blockop blockop; -}; - -template<int N> -struct V4InstrMeta { -}; - -#define QML_V4_INSTR_META_TEMPLATE(I, FMT) \ - template<> struct V4InstrMeta<(int)V4Instr::I> { \ - enum { Size = QML_V4_INSTR_SIZE(I, FMT) }; \ - typedef V4Instr::instr_##FMT DataType; \ - static const DataType &data(const V4Instr &instr) { return instr.FMT; } \ - static void setData(V4Instr &instr, const DataType &v) { instr.FMT = v; } \ - }; -FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE); -#undef QML_V4_INSTR_META_TEMPLATE - -template<int Instr> -class V4InstrData : public V4InstrMeta<Instr>::DataType -{ -}; - -class Bytecode -{ - Q_DISABLE_COPY(Bytecode) - -public: - Bytecode(); - - const char *constData() const { return d.constData(); } - int size() const { return d.size(); } - int count() const { return d.count(); } - void clear() { d.clear(); } - bool isEmpty() const { return d.isEmpty(); } - V4Instr::Type instructionType(const V4Instr *instr) const; - - template <int Instr> - void append(const V4InstrData<Instr> &data) - { - V4Instr genericInstr; - V4InstrMeta<Instr>::setData(genericInstr, data); - return append(static_cast<V4Instr::Type>(Instr), genericInstr); - } - void append(V4Instr::Type type, V4Instr &instr); - - int remove(int index); - - const V4Instr &operator[](int offset) const; - V4Instr &operator[](int offset); - - void dump(const char *start, const char *end) const; - -private: - void dump(const V4Instr *instr, int = -1) const; - - QVarLengthArray<char, 4 * 1024> d; -#ifdef QML_THREADED_INTERPRETER - void **decodeInstr; -#endif -}; - -} - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4INSTRUCTION_P_H - diff --git a/src/declarative/qml/v4/qv4ir.cpp b/src/declarative/qml/v4/qv4ir.cpp deleted file mode 100644 index 6a30e93227..0000000000 --- a/src/declarative/qml/v4/qv4ir.cpp +++ /dev/null @@ -1,883 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4ir_p.h" - -#include <QtCore/qtextstream.h> -#include <QtCore/qdebug.h> -#include <math.h> - -QT_BEGIN_NAMESPACE - -namespace QDeclarativeJS { -namespace IR { - -inline const char *typeName(Type t) -{ - switch (t) { - case InvalidType: return "invalid"; - case UndefinedType: return "undefined"; - case NullType: return "null"; - case VoidType: return "void"; - case StringType: return "string"; - case UrlType: return "url"; - case ColorType: return "color"; - case SGAnchorLineType: return "SGAnchorLine"; - case AttachType: return "AttachType"; - case ObjectType: return "object"; - case BoolType: return "bool"; - case IntType: return "int"; - case RealType: return "qreal"; - case RealNaNType: return "NaN"; - default: return "invalid"; - } -} - -inline bool isNumberType(IR::Type ty) -{ - return ty >= IR::FirstNumberType; -} - -inline bool isStringType(IR::Type ty) -{ - return ty == IR::StringType || ty == IR::UrlType || ty == IR::ColorType; -} - -IR::Type maxType(IR::Type left, IR::Type right) -{ - if (isStringType(left) && isStringType(right)) { - // String promotions (url to string) are more specific than - // identity conversions (AKA left == right). That's because - // we want to ensure we convert urls to strings in binary - // expressions. - return IR::StringType; - } else if (left == right) - return left; - else if (isNumberType(left) && isNumberType(right)) - return qMax(left, right); - else if ((isNumberType(left) && isStringType(right)) || - (isNumberType(right) && isStringType(left))) - return IR::StringType; - else - return IR::InvalidType; -} - - -const char *opname(AluOp op) -{ - switch (op) { - case OpInvalid: return "?"; - - case OpIfTrue: return "(bool)"; - case OpNot: return "!"; - case OpUMinus: return "-"; - case OpUPlus: return "+"; - case OpCompl: return "~"; - - case OpBitAnd: return "&"; - case OpBitOr: return "|"; - case OpBitXor: return "^"; - - case OpAdd: return "+"; - case OpSub: return "-"; - case OpMul: return "*"; - case OpDiv: return "/"; - case OpMod: return "%"; - - case OpLShift: return "<<"; - case OpRShift: return ">>"; - case OpURShift: return ">>>"; - - case OpGt: return ">"; - case OpLt: return "<"; - case OpGe: return ">="; - case OpLe: return "<="; - case OpEqual: return "=="; - case OpNotEqual: return "!="; - case OpStrictEqual: return "==="; - case OpStrictNotEqual: return "!=="; - - case OpAnd: return "&&"; - case OpOr: return "||"; - - default: return "?"; - - } // switch -} - -AluOp binaryOperator(int op) -{ - switch (static_cast<QSOperator::Op>(op)) { - case QSOperator::Add: return OpAdd; - case QSOperator::And: return OpAnd; - case QSOperator::BitAnd: return OpBitAnd; - case QSOperator::BitOr: return OpBitOr; - case QSOperator::BitXor: return OpBitXor; - case QSOperator::Div: return OpDiv; - case QSOperator::Equal: return OpEqual; - case QSOperator::Ge: return OpGe; - case QSOperator::Gt: return OpGt; - case QSOperator::Le: return OpLe; - case QSOperator::LShift: return OpLShift; - case QSOperator::Lt: return OpLt; - case QSOperator::Mod: return OpMod; - case QSOperator::Mul: return OpMul; - case QSOperator::NotEqual: return OpNotEqual; - case QSOperator::Or: return OpOr; - case QSOperator::RShift: return OpRShift; - case QSOperator::StrictEqual: return OpStrictEqual; - case QSOperator::StrictNotEqual: return OpStrictNotEqual; - case QSOperator::Sub: return OpSub; - case QSOperator::URShift: return OpURShift; - default: return OpInvalid; - } -} - -void Const::dump(QTextStream &out) -{ - out << value; -} - -void String::dump(QTextStream &out) -{ - out << '"' << escape(value) << '"'; -} - -QString String::escape(const QStringRef &s) -{ - QString r; - for (int i = 0; i < s.length(); ++i) { - const QChar ch = s.at(i); - if (ch == QLatin1Char('\n')) - r += QLatin1String("\\n"); - else if (ch == QLatin1Char('\r')) - r += QLatin1String("\\r"); - else if (ch == QLatin1Char('\\')) - r += QLatin1String("\\\\"); - else if (ch == QLatin1Char('"')) - r += QLatin1String("\\\""); - else if (ch == QLatin1Char('\'')) - r += QLatin1String("\\'"); - else - r += ch; - } - return r; -} - -void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column) -{ - this->type = type; - this->base = base; - this->id = id; - this->symbol = symbol; - this->ptr = 0; - this->property = 0; - this->storage = MemberStorage; - this->builtin = NoBuiltinSymbol; - this->line = line; - this->column = column; - - if (id->length() == 8 && *id == QLatin1String("Math.sin")) { - builtin = MathSinBultinFunction; - } else if (id->length() == 8 && *id == QLatin1String("Math.cos")) { - builtin = MathCosBultinFunction; - } else if (id->length() == 10 && *id == QLatin1String("Math.round")) { - builtin = MathRoundBultinFunction; - } else if (id->length() == 10 && *id == QLatin1String("Math.floor)")) { - builtin = MathFloorBultinFunction; - } else if (id->length() == 7 && *id == QLatin1String("Math.PI")) { - builtin = MathPIBuiltinConstant; - this->type = RealType; - } -} - -void Name::dump(QTextStream &out) -{ - if (base) { - base->dump(out); - out << '.'; - } - - out << *id; -} - -void Temp::dump(QTextStream &out) -{ - out << 't' << index; -} - -void Unop::dump(QTextStream &out) -{ - out << opname(op); - expr->dump(out); -} - -Type Unop::typeForOp(AluOp op, Expr *expr) -{ - switch (op) { - case OpIfTrue: return BoolType; - case OpNot: return BoolType; - - case OpUMinus: - case OpUPlus: - case OpCompl: - return maxType(expr->type, RealType); - - default: - break; - } - - return InvalidType; -} - -void Binop::dump(QTextStream &out) -{ - left->dump(out); - out << ' ' << opname(op) << ' '; - right->dump(out); -} - -Type Binop::typeForOp(AluOp op, Expr *left, Expr *right) -{ - if (! (left && right)) - return InvalidType; - - switch (op) { - case OpInvalid: - return InvalidType; - - // unary operators - case OpIfTrue: - case OpNot: - case OpUMinus: - case OpUPlus: - case OpCompl: - return InvalidType; - - // bit fields - case OpBitAnd: - case OpBitOr: - case OpBitXor: - return IntType; - - case OpAdd: - if (left->type == StringType) - return StringType; - return RealType; - - case OpSub: - case OpMul: - case OpDiv: - case OpMod: - return RealType; - - case OpLShift: - case OpRShift: - case OpURShift: - return IntType; - - case OpAnd: - case OpOr: - return BoolType; - - case OpGt: - case OpLt: - case OpGe: - case OpLe: - case OpEqual: - case OpNotEqual: - case OpStrictEqual: - case OpStrictNotEqual: - return BoolType; - } // switch - - return InvalidType; -} - -void Call::dump(QTextStream &out) -{ - base->dump(out); - out << '('; - for (ExprList *it = args; it; it = it->next) { - if (it != args) - out << ", "; - it->expr->dump(out); - } - out << ')'; -} - -Type Call::typeForFunction(Expr *base) -{ - if (! base) - return InvalidType; - - if (Name *name = base->asName()) { - switch (name->builtin) { - case MathSinBultinFunction: - case MathCosBultinFunction: - return RealType; - - case MathRoundBultinFunction: - case MathFloorBultinFunction: - return IntType; - - case NoBuiltinSymbol: - case MathPIBuiltinConstant: - break; - } - } // switch - - return InvalidType; -} - -void Exp::dump(QTextStream &out, Mode) -{ - out << "(void) "; - expr->dump(out); - out << ';'; -} - -void Move::dump(QTextStream &out, Mode) -{ - target->dump(out); - out << " = "; - if (source->type != target->type) - out << typeName(source->type) << "_to_" << typeName(target->type) << '('; - source->dump(out); - if (source->type != target->type) - out << ')'; - out << ';'; -} - -void Jump::dump(QTextStream &out, Mode mode) -{ - Q_UNUSED(mode); - out << "goto " << 'L' << target << ';'; -} - -void CJump::dump(QTextStream &out, Mode mode) -{ - Q_UNUSED(mode); - out << "if ("; - cond->dump(out); - out << ") goto " << 'L' << iftrue << "; else goto " << 'L' << iffalse << ';'; -} - -void Ret::dump(QTextStream &out, Mode) -{ - out << "return"; - if (expr) { - out << ' '; - expr->dump(out); - } - out << ';'; -} - -Function::~Function() -{ - qDeleteAll(basicBlocks); -} - -QString *Function::newString(const QString &text) -{ - return pool->NewString(text); -} - -BasicBlock *Function::newBasicBlock() -{ - const int index = basicBlocks.size(); - return i(new BasicBlock(this, index)); -} - -void Function::dump(QTextStream &out) -{ - out << "function () {" << endl; - foreach (BasicBlock *bb, basicBlocks) { - bb->dump(out); - } - out << '}' << endl; -} - -Temp *BasicBlock::TEMP(Type type, int index) -{ - Temp *e = function->pool->New<Temp>(); - e->init(type, index); - return e; -} - -Temp *BasicBlock::TEMP(Type type) -{ - return TEMP(type, function->tempCount++); -} - -Expr *BasicBlock::CONST(double value) -{ - return CONST(IR::RealType, value); -} - -Expr *BasicBlock::CONST(Type type, double value) -{ - Const *e = function->pool->New<Const>(); - e->init(type, value); - return e; -} - -Expr *BasicBlock::STRING(const QStringRef &value) -{ - String *e = function->pool->New<String>(); - e->init(value); - return e; -} - -Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) -{ - return NAME(0, id, line, column); -} - -Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column) -{ - Name *e = function->pool->New<Name>(); - e->init(base, InvalidType, - function->newString(id), - Name::Unbound, line, column); - return e; -} - -Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, - quint32 line, quint32 column) -{ - Name *name = SYMBOL(/*base = */ 0, type, id, meta, property, line, column); - name->storage = storage; - return name; -} - -Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, - quint32 line, quint32 column) -{ - Name *name = function->pool->New<Name>(); - name->init(base, type, function->newString(id), - Name::Property, line, column); - name->meta = meta; - name->property = property; - name->storage = storage; - return name; -} - -Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, - quint32 line, quint32 column) -{ - Name *name = function->pool->New<Name>(); - name->init(base, type, function->newString(id), - Name::Property, line, column); - name->meta = meta; - name->property = property; - return name; -} - -Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeScript::Object *object, quint32 line, quint32 column) -{ - Name *name = function->pool->New<Name>(); - name->init(/*base = */ 0, IR::ObjectType, - function->newString(id), - Name::IdObject, line, column); - name->idObject = object; - name->property = 0; - name->storage = Name::IdStorage; - return name; -} - -Name *BasicBlock::ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, - quint32 line, quint32 column) -{ - Name *name = function->pool->New<Name>(); - name->init(/*base = */ 0, IR::AttachType, - function->newString(id), - Name::AttachType, line, column); - name->declarativeType = attachType; - name->storage = storage; - return name; -} - - -Expr *BasicBlock::UNOP(AluOp op, Expr *expr) -{ - Unop *e = function->pool->New<Unop>(); - e->init(op, expr); - return e; -} - -Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) -{ - if (left && right) { - if (Const *c1 = left->asConst()) { - if (Const *c2 = right->asConst()) { - switch (op) { - case OpAdd: return CONST(c1->value + c2->value); - case OpAnd: return CONST(c1->value ? c2->value : 0); - case OpBitAnd: return CONST(int(c1->value) & int(c2->value)); - case OpBitOr: return CONST(int(c1->value) | int(c2->value)); - case OpBitXor: return CONST(int(c1->value) ^ int(c2->value)); - case OpDiv: return CONST(c1->value / c2->value); - case OpEqual: return CONST(c1->value == c2->value); - case OpGe: return CONST(c1->value >= c2->value); - case OpGt: return CONST(c1->value > c2->value); - case OpLe: return CONST(c1->value <= c2->value); - case OpLShift: return CONST(int(c1->value) << int(c2->value)); - case OpLt: return CONST(c1->value < c2->value); - case OpMod: return CONST(::fmod(c1->value, c2->value)); - case OpMul: return CONST(c1->value * c2->value); - case OpNotEqual: return CONST(c1->value != c2->value); - case OpOr: return CONST(c1->value ? c1->value : c2->value); - case OpRShift: return CONST(int(c1->value) >> int(c2->value)); - case OpStrictEqual: return CONST(c1->value == c2->value); - case OpStrictNotEqual: return CONST(c1->value != c2->value); - case OpSub: return CONST(c1->value - c2->value); - case OpURShift: return CONST(unsigned(c1->value) >> int(c2->value)); - - case OpIfTrue: // unary ops - case OpNot: - case OpUMinus: - case OpUPlus: - case OpCompl: - case OpInvalid: - break; - } - } - } - } - - Binop *e = function->pool->New<Binop>(); - e->init(op, left, right); - return e; -} - -Expr *BasicBlock::CALL(Expr *base, ExprList *args) -{ - Call *e = function->pool->New<Call>(); - e->init(base, args); - return e; -} - -Stmt *BasicBlock::EXP(Expr *expr) -{ - Exp *s = function->pool->New<Exp>(); - s->init(expr); - statements.append(s); - return s; -} - -Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) -{ - Move *s = function->pool->New<Move>(); - s->init(target, source, isMoveForReturn); - statements.append(s); - return s; -} - -Stmt *BasicBlock::JUMP(BasicBlock *target) -{ - if (isTerminated()) - return 0; - - Jump *s = function->pool->New<Jump>(); - s->init(target); - statements.append(s); - return s; -} - -Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) -{ - if (isTerminated()) - return 0; - - CJump *s = function->pool->New<CJump>(); - s->init(cond, iftrue, iffalse); - statements.append(s); - return s; -} - -Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column) -{ - if (isTerminated()) - return 0; - - Ret *s = function->pool->New<Ret>(); - s->init(expr, type, line, column); - statements.append(s); - return s; -} - -void BasicBlock::dump(QTextStream &out) -{ - out << 'L' << this << ':' << endl; - foreach (Stmt *s, statements) { - out << '\t'; - s->dump(out); - out << endl; - } -} - -#ifdef DEBUG_IR_STRUCTURE - -static const char *symbolname(Name::Symbol s) -{ - switch (s) { - case Name::Unbound: - return "Unbound"; - case Name::IdObject: - return "IdObject"; - case Name::AttachType: - return "AttachType"; - case Name::Object: - return "Object"; - case Name::Property: - return "Property"; - case Name::Slot: - return "Slot"; - default: - Q_ASSERT(!"Unreachable"); - return "Unknown"; - } -} - -static const char *storagename(Name::Storage s) -{ - switch (s) { - case Name::MemberStorage: - return "MemberStorage"; - case Name::IdStorage: - return "IdStorage"; - case Name::RootStorage: - return "RootStorage"; - case Name::ScopeStorage: - return "ScopeStorage"; - default: - Q_ASSERT(!"Unreachable"); - return "UnknownStorage"; - } -} - -IRDump::IRDump() -: indentSize(0) -{ -} - -void IRDump::inc() -{ - indentSize++; - indentData = QByteArray(indentSize * 4, ' '); -} - -void IRDump::dec() -{ - indentSize--; - indentData = QByteArray(indentSize * 4, ' '); -} - -void IRDump::dec(); - -void IRDump::expression(QDeclarativeJS::IR::Expr *e) -{ - inc(); - - e->accept(this); - - dec(); -} - -void IRDump::basicblock(QDeclarativeJS::IR::BasicBlock *b) -{ - inc(); - - qWarning().nospace() << indent() << "BasicBlock " << b << " {"; - for (int ii = 0; ii < b->statements.count(); ++ii) { - statement(b->statements.at(ii)); - if (ii != (b->statements.count() - 1)) - qWarning(); - } - qWarning().nospace() << indent() << "}"; - - dec(); -} - -void IRDump::statement(QDeclarativeJS::IR::Stmt *s) -{ - inc(); - - s->accept(this); - - dec(); -} - -void IRDump::function(QDeclarativeJS::IR::Function *f) -{ - inc(); - - qWarning().nospace() << indent() << "Function {"; - for (int ii = 0; ii < f->basicBlocks.count(); ++ii) { - basicblock(f->basicBlocks.at(ii)); - } - qWarning().nospace() << indent() << "}"; - - dec(); -} - -const char *IRDump::indent() -{ - return indentData.constData(); -} - -void IRDump::visitConst(QDeclarativeJS::IR::Const *e) -{ - qWarning().nospace() << indent() << "Const:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; -} - -void IRDump::visitString(QDeclarativeJS::IR::String *e) -{ - qWarning().nospace() << indent() << "String:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; -} - -static void namedumprecur(QDeclarativeJS::IR::Name *e, const char *indent) -{ - if (e->base) namedumprecur(e->base, indent); - qWarning().nospace() << indent << " { type: " << typeName(e->type) << ", symbol: " << symbolname(e->symbol) << ", storage: " << storagename(e->storage) << ", id: " << e->id << "}"; -} - -void IRDump::visitName(QDeclarativeJS::IR::Name *e) -{ - qWarning().nospace() << indent() << "Name:Expr {"; - namedumprecur(e, indent()); - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitTemp(QDeclarativeJS::IR::Temp *e) -{ - qWarning().nospace() << indent() << "Temp:Expr { type: " << typeName(e->type) << ", index: " << e->index << " }"; -} - -void IRDump::visitUnop(QDeclarativeJS::IR::Unop *e) -{ - qWarning().nospace() << indent() << "Unop:Expr { "; - qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); - qWarning().nospace() << indent() << " expr: {"; - expression(e->expr); - qWarning().nospace() << indent() << " }"; - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitBinop(QDeclarativeJS::IR::Binop *e) -{ - qWarning().nospace() << indent() << "Binop:Expr { "; - qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); - qWarning().nospace() << indent() << " left: {"; - inc(); - expression(e->left); - dec(); - qWarning().nospace() << indent() << " },"; - qWarning().nospace() << indent() << " right: {"; - inc(); - expression(e->right); - dec(); - qWarning().nospace() << indent() << " }"; - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitCall(QDeclarativeJS::IR::Call *e) -{ - Q_UNUSED(e); - qWarning().nospace() << indent() << "Exp::Call { }"; -} - -void IRDump::visitExp(QDeclarativeJS::IR::Exp *s) -{ - qWarning().nospace() << indent() << "Exp:Stmt {"; - expression(s->expr); - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitMove(QDeclarativeJS::IR::Move *s) -{ - qWarning().nospace() << indent() << "Move:Stmt {"; - qWarning().nospace() << indent() << " isMoveForReturn: " << s->isMoveForReturn; - qWarning().nospace() << indent() << " target: {"; - inc(); - expression(s->target); - dec(); - qWarning().nospace() << indent() << " },"; - qWarning().nospace() << indent() << " source: {"; - inc(); - expression(s->source); - dec(); - qWarning().nospace() << indent() << " }"; - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitJump(QDeclarativeJS::IR::Jump *s) -{ - qWarning().nospace() << indent() << "Jump:Stmt { BasicBlock(" << s->target << ") }"; -} - -void IRDump::visitCJump(QDeclarativeJS::IR::CJump *s) -{ - qWarning().nospace() << indent() << "CJump:Stmt {"; - qWarning().nospace() << indent() << " cond: {"; - inc(); - expression(s->cond); - dec(); - qWarning().nospace() << indent() << " }"; - qWarning().nospace() << indent() << " iftrue: BasicBlock(" << s->iftrue << ")"; - qWarning().nospace() << indent() << " iffalse: BasicBlock(" << s->iffalse << ")"; - qWarning().nospace() << indent() << "}"; -} - -void IRDump::visitRet(QDeclarativeJS::IR::Ret *s) -{ - qWarning().nospace() << indent() << "Ret:Stmt {"; - qWarning().nospace() << indent() << " type: " << typeName(s->type); - expression(s->expr); - qWarning().nospace() << indent() << "}"; -} -#endif - -} // end of namespace IR -} // end of namespace QDeclarativeJS - -QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qv4ir_p.h b/src/declarative/qml/v4/qv4ir_p.h deleted file mode 100644 index f6aae06f44..0000000000 --- a/src/declarative/qml/v4/qv4ir_p.h +++ /dev/null @@ -1,605 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4IR_P_H -#define QV4IR_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qdeclarativejsast_p.h> -#include <private/qdeclarativejsengine_p.h> -#include <private/qdeclarativescript_p.h> -#include <private/qdeclarativeimport_p.h> -#include <private/qdeclarativeengine_p.h> -#include <private/qv4compiler_p.h> - -#include <private/qdeclarativepool_p.h> -#include <QtCore/qvarlengtharray.h> - -// #define DEBUG_IR_STRUCTURE - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QTextStream; -class QDeclarativeType; - -namespace QDeclarativeJS { - -namespace IR { - -struct BasicBlock; -struct Function; - -struct Stmt; -struct Expr; - -// expressions -struct Const; -struct String; -struct Name; -struct Temp; -struct Unop; -struct Binop; -struct Call; - -// statements -struct Exp; -struct Move; -struct Jump; -struct CJump; -struct Ret; - -enum AluOp { - OpInvalid = 0, - - OpIfTrue, - OpNot, - OpUMinus, - OpUPlus, - OpCompl, - - OpBitAnd, - OpBitOr, - OpBitXor, - - OpAdd, - OpSub, - OpMul, - OpDiv, - OpMod, - - OpLShift, - OpRShift, - OpURShift, - - OpGt, - OpLt, - OpGe, - OpLe, - OpEqual, - OpNotEqual, - OpStrictEqual, - OpStrictNotEqual, - - OpAnd, - OpOr -}; -AluOp binaryOperator(int op); - -enum Type { - InvalidType, - UndefinedType, - NullType, - VoidType, - StringType, - UrlType, - ColorType, - SGAnchorLineType, - AttachType, - ObjectType, - - FirstNumberType, - BoolType = FirstNumberType, - IntType, - RealType, - RealNaNType -}; -Type maxType(IR::Type left, IR::Type right); - -struct ExprVisitor { - virtual ~ExprVisitor() {} - virtual void visitConst(Const *) {} - virtual void visitString(String *) {} - virtual void visitName(Name *) {} - virtual void visitTemp(Temp *) {} - virtual void visitUnop(Unop *) {} - virtual void visitBinop(Binop *) {} - virtual void visitCall(Call *) {} -}; - -struct StmtVisitor { - virtual ~StmtVisitor() {} - virtual void visitExp(Exp *) {} - virtual void visitMove(Move *) {} - virtual void visitJump(Jump *) {} - virtual void visitCJump(CJump *) {} - virtual void visitRet(Ret *) {} -}; - -struct Expr: QDeclarativePool::POD { - Type type; - - Expr(): type(InvalidType) {} - virtual ~Expr() {} - virtual void accept(ExprVisitor *) = 0; - virtual Const *asConst() { return 0; } - virtual String *asString() { return 0; } - virtual Name *asName() { return 0; } - virtual Temp *asTemp() { return 0; } - virtual Unop *asUnop() { return 0; } - virtual Binop *asBinop() { return 0; } - virtual Call *asCall() { return 0; } - virtual void dump(QTextStream &out) = 0; -}; - -struct ExprList: QDeclarativePool::POD { - Expr *expr; - ExprList *next; - - void init(Expr *expr, ExprList *next = 0) - { - this->expr = expr; - this->next = next; - } -}; - -struct Const: Expr { - double value; - - void init(Type type, double value) - { - this->type = type; - this->value = value; - } - - virtual void accept(ExprVisitor *v) { v->visitConst(this); } - virtual Const *asConst() { return this; } - - virtual void dump(QTextStream &out); -}; - -struct String: Expr { - QStringRef value; - - void init(const QStringRef &value) - { - this->type = StringType; - this->value = value; - } - - virtual void accept(ExprVisitor *v) { v->visitString(this); } - virtual String *asString() { return this; } - - virtual void dump(QTextStream &out); - static QString escape(const QStringRef &s); -}; - -enum BuiltinSymbol { - NoBuiltinSymbol, - MathSinBultinFunction, - MathCosBultinFunction, - MathRoundBultinFunction, - MathFloorBultinFunction, - - MathPIBuiltinConstant -}; - -struct Name: Expr { - enum Symbol { - Unbound, - IdObject, // This is a load of a id object. Storage will always be IdStorage - AttachType, // This is a load of an attached object - Object, // XXX what is this for? - Property, // This is a load of a regular property - Slot // XXX what is this for? - }; - - enum Storage { - MemberStorage, // This is a property of a previously fetched object - IdStorage, // This is a load of a id object. Symbol will always be IdObject - RootStorage, // This is a property of the root object - ScopeStorage // This is a property of the scope object - }; - - Name *base; - const QString *id; - Symbol symbol; - union { - void *ptr; - const QMetaObject *meta; - const QDeclarativeType *declarativeType; - const QDeclarativeScript::Object *idObject; - }; - QDeclarativePropertyData *property; - Storage storage; - BuiltinSymbol builtin; - quint32 line; - quint32 column; - - void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column); - - inline bool is(Symbol s) const { return s == symbol; } - inline bool isNot(Symbol s) const { return s != symbol; } - - virtual void accept(ExprVisitor *v) { v->visitName(this); } - virtual Name *asName() { return this; } - - virtual void dump(QTextStream &out); -}; - -struct Temp: Expr { - int index; - - void init(Type type, int index) - { - this->type = type; - this->index = index; - } - - virtual void accept(ExprVisitor *v) { v->visitTemp(this); } - virtual Temp *asTemp() { return this; } - - virtual void dump(QTextStream &out); -}; - -struct Unop: Expr { - AluOp op; - Expr *expr; - - void init(AluOp op, Expr *expr) - { - this->type = this->typeForOp(op, expr); - this->op = op; - this->expr = expr; - } - - virtual void accept(ExprVisitor *v) { v->visitUnop(this); } - virtual Unop *asUnop() { return this; } - - virtual void dump(QTextStream &out); - -private: - static Type typeForOp(AluOp op, Expr *expr); -}; - -struct Binop: Expr { - AluOp op; - Expr *left; - Expr *right; - - void init(AluOp op, Expr *left, Expr *right) - { - this->type = typeForOp(op, left, right); - this->op = op; - this->left = left; - this->right = right; - } - - virtual void accept(ExprVisitor *v) { v->visitBinop(this); } - virtual Binop *asBinop() { return this; } - - virtual void dump(QTextStream &out); - -private: - static Type typeForOp(AluOp op, Expr *left, Expr *right); -}; - -struct Call: Expr { - Expr *base; - ExprList *args; - - void init(Expr *base, ExprList *args) - { - this->type = typeForFunction(base); - this->base = base; - this->args = args; - } - - Expr *onlyArgument() const { - if (args && ! args->next) - return args->expr; - return 0; - } - - virtual void accept(ExprVisitor *v) { v->visitCall(this); } - virtual Call *asCall() { return this; } - - virtual void dump(QTextStream &out); - -private: - static Type typeForFunction(Expr *base); -}; - -struct Stmt: QDeclarativePool::POD { - enum Mode { - HIR, - MIR - }; - - virtual ~Stmt() {} - virtual Stmt *asTerminator() { return 0; } - - virtual void accept(StmtVisitor *) = 0; - virtual Exp *asExp() { return 0; } - virtual Move *asMove() { return 0; } - virtual Jump *asJump() { return 0; } - virtual CJump *asCJump() { return 0; } - virtual Ret *asRet() { return 0; } - virtual void dump(QTextStream &out, Mode mode = HIR) = 0; -}; - -struct Exp: Stmt { - Expr *expr; - - void init(Expr *expr) - { - this->expr = expr; - } - - virtual void accept(StmtVisitor *v) { v->visitExp(this); } - virtual Exp *asExp() { return this; } - - virtual void dump(QTextStream &out, Mode); -}; - -struct Move: Stmt { - Expr *target; - Expr *source; - bool isMoveForReturn; - - void init(Expr *target, Expr *source, bool isMoveForReturn) - { - this->target = target; - this->source = source; - this->isMoveForReturn = isMoveForReturn; - } - - virtual void accept(StmtVisitor *v) { v->visitMove(this); } - virtual Move *asMove() { return this; } - - virtual void dump(QTextStream &out, Mode); -}; - -struct Jump: Stmt { - BasicBlock *target; - - void init(BasicBlock *target) - { - this->target = target; - } - - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitJump(this); } - virtual Jump *asJump() { return this; } - - virtual void dump(QTextStream &out, Mode mode); -}; - -struct CJump: Stmt { - Expr *cond; - BasicBlock *iftrue; - BasicBlock *iffalse; - - void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) - { - this->cond = cond; - this->iftrue = iftrue; - this->iffalse = iffalse; - } - - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitCJump(this); } - virtual CJump *asCJump() { return this; } - - virtual void dump(QTextStream &out, Mode mode); -}; - -struct Ret: Stmt { - Expr *expr; - Type type; - quint32 line; - quint32 column; - - void init(Expr *expr, Type type, quint32 line, quint32 column) - { - this->expr = expr; - this->type = type; - this->line = line; - this->column = column; - } - - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitRet(this); } - virtual Ret *asRet() { return this; } - - virtual void dump(QTextStream &out, Mode); -}; - -struct Function { - QDeclarativePool *pool; - QVarLengthArray<BasicBlock *, 8> basicBlocks; - int tempCount; - - Function(QDeclarativePool *pool) - : pool(pool), tempCount(0) {} - - ~Function(); - - BasicBlock *newBasicBlock(); - QString *newString(const QString &text); - - inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; } - - virtual void dump(QTextStream &out); -}; - -struct BasicBlock { - Function *function; - int index; - int offset; - QVarLengthArray<Stmt *, 32> statements; - - BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {} - ~BasicBlock() {} - - template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; } - - inline bool isEmpty() const { - return statements.isEmpty(); - } - - inline Stmt *terminator() const { - if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0) - return statements.at(statements.size() - 1); - return 0; - } - - inline bool isTerminated() const { - if (terminator() != 0) - return true; - return false; - } - - Temp *TEMP(Type type, int index); - Temp *TEMP(Type type); - - Expr *CONST(double value); - Expr *CONST(Type type, double value); - Expr *STRING(const QStringRef &value); - - Name *NAME(const QString &id, quint32 line, quint32 column); - Name *NAME(Name *base, const QString &id, quint32 line, quint32 column); - Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, quint32 line, quint32 column); - Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, quint32 line, quint32 column); - Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, quint32 line, quint32 column); - Name *ID_OBJECT(const QString &id, const QDeclarativeScript::Object *object, quint32 line, quint32 column); - Name *ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, quint32 line, quint32 column); - - Expr *UNOP(AluOp op, Expr *expr); - Expr *BINOP(AluOp op, Expr *left, Expr *right); - Expr *CALL(Expr *base, ExprList *args); - - Stmt *EXP(Expr *expr); - Stmt *MOVE(Expr *target, Expr *source, bool = false); - - Stmt *JUMP(BasicBlock *target); - Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse); - Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column); - - virtual void dump(QTextStream &out); -}; - -#ifdef DEBUG_IR_STRUCTURE -struct IRDump : public ExprVisitor, - public StmtVisitor -{ -public: - IRDump(); - - void expression(QDeclarativeJS::IR::Expr *); - void basicblock(QDeclarativeJS::IR::BasicBlock *); - void statement(QDeclarativeJS::IR::Stmt *); - void function(QDeclarativeJS::IR::Function *); -protected: - - const char *indent(); - - // - // expressions - // - virtual void visitConst(QDeclarativeJS::IR::Const *e); - virtual void visitString(QDeclarativeJS::IR::String *e); - virtual void visitName(QDeclarativeJS::IR::Name *e); - virtual void visitTemp(QDeclarativeJS::IR::Temp *e); - virtual void visitUnop(QDeclarativeJS::IR::Unop *e); - virtual void visitBinop(QDeclarativeJS::IR::Binop *e); - virtual void visitCall(QDeclarativeJS::IR::Call *e); - - // - // statements - // - virtual void visitExp(QDeclarativeJS::IR::Exp *s); - virtual void visitMove(QDeclarativeJS::IR::Move *s); - virtual void visitJump(QDeclarativeJS::IR::Jump *s); - virtual void visitCJump(QDeclarativeJS::IR::CJump *s); - virtual void visitRet(QDeclarativeJS::IR::Ret *s); - -private: - int indentSize; - QByteArray indentData; - void inc(); - void dec(); -}; -#endif - -} // end of namespace IR - -} // end of namespace QDeclarativeJS - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4IR_P_H diff --git a/src/declarative/qml/v4/qv4irbuilder.cpp b/src/declarative/qml/v4/qv4irbuilder.cpp deleted file mode 100644 index e9f02b0c2f..0000000000 --- a/src/declarative/qml/v4/qv4irbuilder.cpp +++ /dev/null @@ -1,1305 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4irbuilder_p.h" -#include "qv4compiler_p_p.h" - -#include <private/qdeclarativemetatype_p.h> -#include <private/qdeclarativetypenamecache_p.h> - -DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) - -QT_BEGIN_NAMESPACE - -using namespace QDeclarativeJS; - -static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, const QMetaObject * /* meta */) -{ - switch (t) { - case QMetaType::Bool: - return IR::BoolType; - - case QMetaType::Int: - return IR::IntType; - - case QMetaType::QReal: - return IR::RealType; - - case QMetaType::QString: - return IR::StringType; - - case QMetaType::QUrl: - return IR::UrlType; - - case QMetaType::QColor: - return IR::ColorType; - - default: - if (t == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) { - return IR::SGAnchorLineType; - } else if (engine->metaObjectForType(t)) { - return IR::ObjectType; - } - - return IR::InvalidType; - } -} - -QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr, - QDeclarativeEnginePrivate *engine) -: m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false) -{ -} - -bool QV4IRBuilder::operator()(QDeclarativeJS::IR::Function *function, - QDeclarativeJS::AST::Node *ast) -{ - bool discarded = false; - - IR::BasicBlock *block = function->newBasicBlock(); - - qSwap(_discard, discarded); - qSwap(_function, function); - qSwap(_block, block); - - ExprResult r; - AST::SourceLocation location; - if (AST::ExpressionNode *asExpr = ast->expressionCast()) { - r = expression(asExpr); - location = asExpr->firstSourceLocation(); - } else if (AST::Statement *asStmt = ast->statementCast()) { - r = statement(asStmt); - location = asStmt->firstSourceLocation(); - } - - //_block->MOVE(_block->TEMP(IR::InvalidType), r.code); - if (r.code) { - const QMetaObject *m = 0; - const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m); - if (targetType != r.type()) { - IR::Expr *x = _block->TEMP(targetType); - _block->MOVE(x, r, true); - r.code = x; - } - _block->RET(r.code, targetType, location.startLine, location.startColumn); - } - - qSwap(_block, block); - qSwap(_function, function); - qSwap(_discard, discarded); - - return !discarded; -} - -bool QV4IRBuilder::buildName(QList<QStringRef> &name, - AST::Node *node, - QList<AST::ExpressionNode *> *nodes) -{ - if (node->kind == AST::Node::Kind_IdentifierExpression) { - name << static_cast<AST::IdentifierExpression*>(node)->name; - if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node); - } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { - AST::FieldMemberExpression *expr = - static_cast<AST::FieldMemberExpression *>(node); - - if (!buildName(name, expr->base, nodes)) - return false; - - name << expr->name; - if (nodes) *nodes << expr; - } else { - return false; - } - - return true; -} - -void QV4IRBuilder::discard() -{ - _discard = true; -} - -QV4IRBuilder::ExprResult -QV4IRBuilder::expression(AST::ExpressionNode *ast) -{ - ExprResult r; - if (ast) { - qSwap(_expr, r); - accept(ast); - qSwap(_expr, r); - - if (r.is(IR::InvalidType)) - discard(); - else { - Q_ASSERT(r.hint == r.format); - } - } - - return r; -} - -void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse) -{ - if (! ast) - return; - ExprResult r(iftrue, iffalse); - qSwap(_expr, r); - accept(ast); - qSwap(_expr, r); - - if (r.format != ExprResult::cx) { - if (! r.code) - discard(); - - Q_ASSERT(r.hint == ExprResult::cx); - Q_ASSERT(r.format == ExprResult::ex); - - if (r.type() != IR::BoolType) { - IR::Temp *t = _block->TEMP(IR::BoolType); - _block->MOVE(t, r); - r = t; - } - - _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse); - } -} - -QV4IRBuilder::ExprResult -QV4IRBuilder::statement(AST::Statement *ast) -{ - ExprResult r; - if (ast) { - qSwap(_expr, r); - accept(ast); - qSwap(_expr, r); - - if (r.is(IR::InvalidType)) - discard(); - else { - Q_ASSERT(r.hint == r.format); - } - } - - return r; -} - -void QV4IRBuilder::sourceElement(AST::SourceElement *ast) -{ - accept(ast); -} - -void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type) -{ - if (expr.type() == type) - return; // nothing to do - - IR::Expr *x = _block->TEMP(type); - _block->MOVE(x, expr.code); - expr.code = x; -} - -// QML -bool QV4IRBuilder::visit(AST::UiProgram *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiImportList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiImport *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiPublicMember *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiSourceElement *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiObjectDefinition *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiObjectInitializer *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiObjectBinding *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiScriptBinding *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiArrayBinding *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiObjectMemberList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiArrayMemberList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::UiQualifiedId *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - - -// JS -bool QV4IRBuilder::visit(AST::Program *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::SourceElements *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::FunctionSourceElement *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::StatementSourceElement *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -// object literals -bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::IdentifierPropertyName *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - - -// array literals -bool QV4IRBuilder::visit(AST::ElementList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -bool QV4IRBuilder::visit(AST::Elision *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - - -// function calls -bool QV4IRBuilder::visit(AST::ArgumentList *) -{ - Q_ASSERT(!"unreachable"); - return false; -} - -// expressions -bool QV4IRBuilder::visit(AST::ObjectLiteral *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ArrayLiteral *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ThisExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) -{ - const quint32 line = ast->identifierToken.startLine; - const quint32 column = ast->identifierToken.startColumn; - - const QString name = ast->name.toString(); - - if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) { - _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value - } else if (m_engine->v8engine()->illegalNames().contains(name) ) { - if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name; - return false; - } else if (const QDeclarativeScript::Object *obj = m_expression->ids->value(name)) { - IR::Name *code = _block->ID_OBJECT(name, obj, line, column); - if (obj == m_expression->component) - code->storage = IR::Name::RootStorage; - _expr.code = code; - } else { - - QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name); - if (r.isValid()) { - if (r.type) { - _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); - } - // We don't support anything else - } else { - bool found = false; - - if (m_expression->context != m_expression->component) { - // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same - QDeclarativePropertyCache *cache = m_expression->context->synthCache; - const QMetaObject *metaObject = m_expression->context->metaObject(); - if (!cache) cache = m_engine->cache(metaObject); - - QDeclarativePropertyData *data = cache->property(name); - - if (data && data->hasRevision()) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; - } - - if (data && !data->isFunction()) { - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); - _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::ScopeStorage, line, column); - found = true; - } - } - - if (!found) { - QDeclarativePropertyCache *cache = m_expression->component->synthCache; - const QMetaObject *metaObject = m_expression->component->metaObject(); - if (!cache) cache = m_engine->cache(metaObject); - - QDeclarativePropertyData *data = cache->property(name); - - if (data && data->hasRevision()) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; - } - - if (data && !data->isFunction()) { - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); - _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::RootStorage, line, column); - found = true; - } - } - - if (!found && qmlVerboseCompiler()) - qWarning() << "*** unknown symbol:" << name; - } - } - - if (_expr.code && _expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - - if (_expr.type() != IR::BoolType) { - IR::Temp *t = _block->TEMP(IR::BoolType); - _block->MOVE(t, _expr); - _expr.code = t; - } - - _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse); - _expr.code = 0; - } - - return false; -} - -bool QV4IRBuilder::visit(AST::NullExpression *) -{ - // ### TODO: cx format - _expr.code = _block->CONST(IR::NullType, 0); - return false; -} - -bool QV4IRBuilder::visit(AST::TrueLiteral *) -{ - // ### TODO: cx format - _expr.code = _block->CONST(IR::BoolType, 1); - return false; -} - -bool QV4IRBuilder::visit(AST::FalseLiteral *) -{ - // ### TODO: cx format - _expr.code = _block->CONST(IR::BoolType, 0); - return false; -} - -bool QV4IRBuilder::visit(AST::StringLiteral *ast) -{ - // ### TODO: cx format - _expr.code = _block->STRING(ast->value); - return false; -} - -bool QV4IRBuilder::visit(AST::NumericLiteral *ast) -{ - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse); - } else { - _expr.code = _block->CONST(ast->value); - } - return false; -} - -bool QV4IRBuilder::visit(AST::RegExpLiteral *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::NestedExpression *) -{ - return true; // the value of the nested expression -} - -bool QV4IRBuilder::visit(AST::ArrayMemberExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast) -{ - if (IR::Expr *left = expression(ast->base)) { - if (IR::Name *baseName = left->asName()) { - const quint32 line = ast->identifierToken.startLine; - const quint32 column = ast->identifierToken.startColumn; - - QString name = ast->name.toString(); - - switch(baseName->symbol) { - case IR::Name::Unbound: - break; - - case IR::Name::AttachType: - if (name.at(0).isUpper()) { - QByteArray utf8Name = name.toUtf8(); - const char *enumName = utf8Name.constData(); - - const QMetaObject *meta = baseName->declarativeType->metaObject(); - bool found = false; - for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) { - QMetaEnum e = meta->enumerator(ii); - for (int jj = 0; !found && jj < e.keyCount(); ++jj) { - if (0 == strcmp(e.key(jj), enumName)) { - found = true; - _expr.code = _block->CONST(IR::IntType, e.value(jj)); - } - } - } - - if (!found && qmlVerboseCompiler()) - qWarning() << "*** unresolved enum:" - << (*baseName->id + QLatin1String(".") + ast->name.toString()); - } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) { - QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta); - QDeclarativePropertyData *data = cache->property(name); - - if (!data || data->isFunction()) - return false; // Don't support methods (or non-existing properties ;) - - if(!data->isFinal()) { - if (qmlVerboseCompiler()) - qWarning() << "*** non-final attached property:" - << (*baseName->id + QLatin1String(".") + ast->name.toString()); - return false; // We don't know enough about this property - } - - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta); - _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column); - } - break; - - case IR::Name::IdObject: { - const QDeclarativeScript::Object *idObject = baseName->idObject; - QDeclarativePropertyCache *cache = - idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject()); - - QDeclarativePropertyData *data = cache->property(name); - - if (!data || data->isFunction()) - return false; // Don't support methods (or non-existing properties ;) - - if (data->hasRevision()) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; - } - - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject()); - _expr.code = _block->SYMBOL(baseName, irType, name, - idObject->metaObject(), data, line, column); - } - break; - - case IR::Name::Property: - if (baseName->type == IR::ObjectType && baseName->meta && baseName->property->isFinal()) { - QDeclarativePropertyCache *cache = m_engine->cache(baseName->meta); - if (!cache) - return false; - - if (QDeclarativePropertyData *data = cache->property(name)) { - if (!data->isFinal()) { - if (qmlVerboseCompiler()) - qWarning() << "*** non-final property access:" - << (*baseName->id + QLatin1String(".") + ast->name.toString()); - return false; // We don't know enough about this property - } - - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta); - _expr.code = _block->SYMBOL(baseName, irType, name, - baseName->meta, data, line, column); - } - } - break; - - case IR::Name::Object: - case IR::Name::Slot: - break; - } - } - } - - return false; -} - -bool QV4IRBuilder::preVisit(AST::Node *) -{ - return ! _discard; -} - -bool QV4IRBuilder::visit(AST::NewMemberExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::NewExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::CallExpression *ast) -{ - QList<QStringRef> names; - QList<AST::ExpressionNode *> nameNodes; - - names.reserve(4); - nameNodes.reserve(4); - - if (buildName(names, ast->base, &nameNodes)) { - //ExprResult base = expression(ast->base); - QString id; - for (int i = 0; i < names.size(); ++i) { - if (! i) - id += QLatin1Char('.'); - id += names.at(i); - } - const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation(); - IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn); - - IR::ExprList *args = 0, **argsInserter = &args; - for (AST::ArgumentList *it = ast->arguments; it; it = it->next) { - IR::Expr *arg = expression(it->expression); - *argsInserter = _function->pool->New<IR::ExprList>(); - (*argsInserter)->init(arg); - argsInserter = &(*argsInserter)->next; - } - - IR::Temp *r = _block->TEMP(IR::InvalidType); - IR::Expr *call = _block->CALL(base, args); - _block->MOVE(r, call); - r->type = call->type; - _expr.code = r; - } - - return false; -} - -bool QV4IRBuilder::visit(AST::PostIncrementExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::PostDecrementExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::DeleteExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::VoidExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::TypeOfExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::PreIncrementExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::PreDecrementExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast) -{ - ExprResult expr = expression(ast->expression); - if (expr.isNot(IR::InvalidType)) { - if (expr.code->asConst() != 0) { - _expr = expr; - return false; - } - - IR::Expr *code = _block->UNOP(IR::OpUPlus, expr); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr, code); - } - - return false; -} - -bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast) -{ - ExprResult expr = expression(ast->expression); - if (expr.isNot(IR::InvalidType)) { - if (IR::Const *c = expr.code->asConst()) { - _expr = expr; - _expr.code = _block->CONST(-c->value); - return false; - } - - IR::Expr *code = _block->UNOP(IR::OpUMinus, expr); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr, code); - } - - return false; -} - -bool QV4IRBuilder::visit(AST::TildeExpression *ast) -{ - ExprResult expr = expression(ast->expression); - if (expr.isNot(IR::InvalidType)) { - if (IR::Const *c = expr.code->asConst()) { - _expr = expr; - _expr.code = _block->CONST(~int(c->value)); - return false; - } - IR::Expr *code = _block->UNOP(IR::OpCompl, expr); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr, code); - } - - return false; -} - -bool QV4IRBuilder::visit(AST::NotExpression *ast) -{ - ExprResult expr = expression(ast->expression); - - if (expr.isNot(IR::InvalidType)) { - if (IR::Const *c = expr.code->asConst()) { - _expr = expr; - _expr.code = _block->CONST(!c->value); - return false; - } - - IR::Expr *code = _block->UNOP(IR::OpNot, expr); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr, code); - - } else if (expr.hint == ExprResult::cx) { - expr.format = ExprResult::cx; - _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse); - return false; - } - - return false; -} - -void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right) -{ - if (IR::Type t = maxType(left.type(), right.type())) { - implicitCvt(left, t); - implicitCvt(right, t); - - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); - } else { - IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr.code, code); - } - } -} - -bool QV4IRBuilder::visit(AST::BinaryExpression *ast) -{ - switch (ast->op) { - case QSOperator::And: { - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - - Q_ASSERT(_expr.iffalse != 0); - Q_ASSERT(_expr.iftrue != 0); - - IR::BasicBlock *iftrue = _function->newBasicBlock(); - condition(ast->left, iftrue, _expr.iffalse); - - _block = iftrue; - condition(ast->right, _expr.iftrue, _expr.iffalse); - } else { - IR::BasicBlock *iftrue = _function->newBasicBlock(); - IR::BasicBlock *iffalse = _function->newBasicBlock(); - IR::BasicBlock *endif = _function->newBasicBlock(); - - condition(ast->left, iftrue, iffalse); - - IR::Temp *r = _block->TEMP(IR::InvalidType); - - _block = iffalse; - _block->MOVE(r, _block->CONST(0)); // ### use the right null value - _block->JUMP(endif); - - _block = iftrue; - ExprResult right = expression(ast->right); - _block->MOVE(r, right); - _block->JUMP(endif); - - _block = endif; - - r->type = right.type(); // ### not exactly, it can be IR::BoolType. - _expr.code = r; - } - } break; - - case QSOperator::Or: { - IR::BasicBlock *iftrue = _function->newBasicBlock(); - IR::BasicBlock *endif = _function->newBasicBlock(); - - ExprResult left = expression(ast->left); - IR::Temp *r = _block->TEMP(left.type()); - _block->MOVE(r, left); - - IR::Expr *cond = r; - if (r->type != IR::BoolType) { - cond = _block->TEMP(IR::BoolType); - _block->MOVE(cond, r); - } - - _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif); - - _block = iftrue; - ExprResult right = expression(ast->right); - _block->MOVE(r, right); - _block->JUMP(endif); - - if (left.type() != right.type()) - discard(); - - _expr.code = r; - - _block = endif; - } break; - - case QSOperator::Lt: - case QSOperator::Gt: - case QSOperator::Le: - case QSOperator::Ge: { - ExprResult left = expression(ast->left); - ExprResult right = expression(ast->right); - if (left.type() == IR::StringType && right.type() == IR::StringType) { - binop(ast, left, right); - } else if (left.isValid() && right.isValid()) { - implicitCvt(left, IR::RealType); - implicitCvt(right, IR::RealType); - binop(ast, left, right); - } - } break; - - case QSOperator::NotEqual: - case QSOperator::Equal: { - ExprResult left = expression(ast->left); - ExprResult right = expression(ast->right); - if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) && - (right.type() == IR::NullType || right.type() == IR::UndefinedType)) { - const bool isEq = ast->op == QSOperator::Equal; - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); - } else { - _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); - } - } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) || - (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) { - implicitCvt(left, IR::RealType); - implicitCvt(right, IR::RealType); - binop(ast, left, right); - } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) { - implicitCvt(left, IR::BoolType); - implicitCvt(right, IR::BoolType); - } else if (left.isValid() && right.isValid()) { - binop(ast, left, right); - } - } break; - - case QSOperator::StrictEqual: - case QSOperator::StrictNotEqual: { - ExprResult left = expression(ast->left); - ExprResult right = expression(ast->right); - if (left.type() == right.type()) { - binop(ast, left, right); - } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) { - // left and right have numeric type (int or real) - binop(ast, left, right); - } else if (left.isValid() && right.isValid()) { - const bool isEq = ast->op == QSOperator::StrictEqual; - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); - } else { - _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); - } - } - } break; - - case QSOperator::BitAnd: - case QSOperator::BitOr: - case QSOperator::BitXor: - case QSOperator::LShift: - case QSOperator::RShift: - case QSOperator::URShift: { - ExprResult left = expression(ast->left); - if (left.is(IR::InvalidType)) - return false; - - ExprResult right = expression(ast->right); - if (right.is(IR::InvalidType)) - return false; - - implicitCvt(left, IR::IntType); - implicitCvt(right, IR::IntType); - - IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr.code, code); - - } break; - - case QSOperator::Add: { - ExprResult left = expression(ast->left); - if (left.is(IR::InvalidType)) - return false; - - ExprResult right = expression(ast->right); - if (right.is(IR::InvalidType)) - return false; - - if (left.isPrimitive() && right.isPrimitive()) { - if (left.type() == IR::StringType || right.type() == IR::StringType) { - implicitCvt(left, IR::StringType); - implicitCvt(right, IR::StringType); - } - binop(ast, left, right); - } - } break; - - case QSOperator::Div: - case QSOperator::Mod: - case QSOperator::Mul: - case QSOperator::Sub: { - ExprResult left = expression(ast->left); - if (left.is(IR::InvalidType)) - return false; - - ExprResult right = expression(ast->right); - if (right.is(IR::InvalidType)) - return false; - - IR::Type t = maxType(left.type(), right.type()); - if (t >= IR::FirstNumberType) { - implicitCvt(left, IR::RealType); - implicitCvt(right, IR::RealType); - - IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); - _expr.code = _block->TEMP(code->type); - _block->MOVE(_expr.code, code); - } - } break; - - case QSOperator::In: - case QSOperator::InstanceOf: - case QSOperator::Assign: - case QSOperator::InplaceAnd: - case QSOperator::InplaceSub: - case QSOperator::InplaceDiv: - case QSOperator::InplaceAdd: - case QSOperator::InplaceLeftShift: - case QSOperator::InplaceMod: - case QSOperator::InplaceMul: - case QSOperator::InplaceOr: - case QSOperator::InplaceRightShift: - case QSOperator::InplaceURightShift: - case QSOperator::InplaceXor: - // yup, we don't do those. - break; - } // switch - - return false; -} - -bool QV4IRBuilder::visit(AST::ConditionalExpression *ast) -{ - IR::BasicBlock *iftrue = _function->newBasicBlock(); - IR::BasicBlock *iffalse = _function->newBasicBlock(); - IR::BasicBlock *endif = _function->newBasicBlock(); - - condition(ast->expression, iftrue, iffalse); - - IR::Temp *r = _block->TEMP(IR::InvalidType); - - qSwap(_block, iftrue); - ExprResult ok = expression(ast->ok); - _block->MOVE(r, ok); - _block->JUMP(endif); - qSwap(_block, iftrue); - - qSwap(_block, iffalse); - ExprResult ko = expression(ast->ko); - _block->MOVE(r, ko); - _block->JUMP(endif); - qSwap(_block, iffalse); - - r->type = maxType(ok.type(), ko.type()); - _expr.code = r; - - _block = endif; - - return false; -} - -bool QV4IRBuilder::visit(AST::Expression *ast) -{ - _block->EXP(expression(ast->left)); - _expr = expression(ast->right); - - return false; -} - - -// statements -bool QV4IRBuilder::visit(AST::Block *ast) -{ - if (ast->statements && ! ast->statements->next) { - // we have one and only one statement - accept(ast->statements->statement); - } - - return false; -} - -bool QV4IRBuilder::visit(AST::StatementList *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::VariableStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::VariableDeclarationList *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::VariableDeclaration *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::EmptyStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ExpressionStatement *ast) -{ - if (ast->expression) { - // return the value of this expression - return true; - } - - return false; -} - -bool QV4IRBuilder::visit(AST::IfStatement *ast) -{ - if (! ast->ko) { - // This is an if statement without an else branch. - discard(); - } else { - IR::BasicBlock *iftrue = _function->newBasicBlock(); - IR::BasicBlock *iffalse = _function->newBasicBlock(); - IR::BasicBlock *endif = _function->newBasicBlock(); - - condition(ast->expression, iftrue, iffalse); - - IR::Temp *r = _block->TEMP(IR::InvalidType); - - qSwap(_block, iftrue); - ExprResult ok = statement(ast->ok); - _block->MOVE(r, ok); - _block->JUMP(endif); - qSwap(_block, iftrue); - - qSwap(_block, iffalse); - ExprResult ko = statement(ast->ko); - _block->MOVE(r, ko); - _block->JUMP(endif); - qSwap(_block, iffalse); - - r->type = maxType(ok.type(), ko.type()); - _expr.code = r; - - _block = endif; - } - - return false; -} - -bool QV4IRBuilder::visit(AST::DoWhileStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::WhileStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ForStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::LocalForStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ForEachStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::LocalForEachStatement *) -{ - discard(); - return false; -} - -bool QV4IRBuilder::visit(AST::ContinueStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::BreakStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ReturnStatement *ast) -{ - if (ast->expression) { - // return the value of the expression - return true; - } - - return false; -} - -bool QV4IRBuilder::visit(AST::WithStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::SwitchStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::CaseBlock *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::CaseClauses *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::CaseClause *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::DefaultClause *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::LabelledStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::ThrowStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::TryStatement *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::Catch *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::Finally *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::FunctionDeclaration *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::FunctionExpression *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::FormalParameterList *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::FunctionBody *) -{ - return false; -} - -bool QV4IRBuilder::visit(AST::DebuggerStatement *) -{ - return false; -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qv4irbuilder_p.h b/src/declarative/qml/v4/qv4irbuilder_p.h deleted file mode 100644 index c0c7ff874c..0000000000 --- a/src/declarative/qml/v4/qv4irbuilder_p.h +++ /dev/null @@ -1,240 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4IRBUILDER_P_H -#define QV4IRBUILDER_P_H - -#include <QtCore/qglobal.h> - -#include "qv4ir_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QV4IRBuilder : public QDeclarativeJS::AST::Visitor -{ -public: - QV4IRBuilder(const QV4Compiler::Expression *, QDeclarativeEnginePrivate *); - - bool operator()(QDeclarativeJS::IR::Function *, QDeclarativeJS::AST::Node *); - -protected: - struct ExprResult { - enum Format { - ex, // expression - cx // condition - }; - - QDeclarativeJS::IR::Expr *code; - QDeclarativeJS::IR::BasicBlock *iftrue; - QDeclarativeJS::IR::BasicBlock *iffalse; - Format hint; // requested format - Format format; // instruction format - - ExprResult(QDeclarativeJS::IR::Expr *expr = 0) - : code(expr), iftrue(0), iffalse(0), hint(ex), format(ex) {} - - ExprResult(QDeclarativeJS::IR::BasicBlock *iftrue, QDeclarativeJS::IR::BasicBlock *iffalse) - : code(0), iftrue(iftrue), iffalse(iffalse), hint(cx), format(ex) {} - - inline QDeclarativeJS::IR::Type type() const { return code ? code->type : QDeclarativeJS::IR::InvalidType; } - - inline QDeclarativeJS::IR::Expr *get() const { return code; } - inline operator QDeclarativeJS::IR::Expr *() const { return get(); } - inline QDeclarativeJS::IR::Expr *operator->() const { return get(); } - inline bool isValid() const { return code ? code->type != QDeclarativeJS::IR::InvalidType : false; } - inline bool is(QDeclarativeJS::IR::Type t) const { return type() == t; } - inline bool isNot(QDeclarativeJS::IR::Type t) const { return type() != t; } - - bool isPrimitive() const { - switch (type()) { - case QDeclarativeJS::IR::UndefinedType: // ### TODO - case QDeclarativeJS::IR::NullType: // ### TODO - case QDeclarativeJS::IR::UrlType: // ### TODO - return false; - - case QDeclarativeJS::IR::StringType: - case QDeclarativeJS::IR::BoolType: - case QDeclarativeJS::IR::IntType: - case QDeclarativeJS::IR::RealType: - case QDeclarativeJS::IR::RealNaNType: - return true; - - default: - return false; - } // switch - } - }; - - inline void accept(QDeclarativeJS::AST::Node *ast) { QDeclarativeJS::AST::Node::accept(ast, this); } - - ExprResult expression(QDeclarativeJS::AST::ExpressionNode *ast); - ExprResult statement(QDeclarativeJS::AST::Statement *ast); - void sourceElement(QDeclarativeJS::AST::SourceElement *ast); - void condition(QDeclarativeJS::AST::ExpressionNode *ast, QDeclarativeJS::IR::BasicBlock *iftrue, QDeclarativeJS::IR::BasicBlock *iffalse); - void binop(QDeclarativeJS::AST::BinaryExpression *ast, ExprResult left, ExprResult right); - - void implicitCvt(ExprResult &expr, QDeclarativeJS::IR::Type type); - - virtual bool preVisit(QDeclarativeJS::AST::Node *ast); - - // QML - virtual bool visit(QDeclarativeJS::AST::UiProgram *ast); - virtual bool visit(QDeclarativeJS::AST::UiImportList *ast); - virtual bool visit(QDeclarativeJS::AST::UiImport *ast); - virtual bool visit(QDeclarativeJS::AST::UiPublicMember *ast); - virtual bool visit(QDeclarativeJS::AST::UiSourceElement *ast); - virtual bool visit(QDeclarativeJS::AST::UiObjectDefinition *ast); - virtual bool visit(QDeclarativeJS::AST::UiObjectInitializer *ast); - virtual bool visit(QDeclarativeJS::AST::UiObjectBinding *ast); - virtual bool visit(QDeclarativeJS::AST::UiScriptBinding *ast); - virtual bool visit(QDeclarativeJS::AST::UiArrayBinding *ast); - virtual bool visit(QDeclarativeJS::AST::UiObjectMemberList *ast); - virtual bool visit(QDeclarativeJS::AST::UiArrayMemberList *ast); - virtual bool visit(QDeclarativeJS::AST::UiQualifiedId *ast); - - // JS - virtual bool visit(QDeclarativeJS::AST::Program *ast); - virtual bool visit(QDeclarativeJS::AST::SourceElements *ast); - virtual bool visit(QDeclarativeJS::AST::FunctionSourceElement *ast); - virtual bool visit(QDeclarativeJS::AST::StatementSourceElement *ast); - - // object literals - virtual bool visit(QDeclarativeJS::AST::PropertyNameAndValueList *ast); - virtual bool visit(QDeclarativeJS::AST::IdentifierPropertyName *ast); - virtual bool visit(QDeclarativeJS::AST::StringLiteralPropertyName *ast); - virtual bool visit(QDeclarativeJS::AST::NumericLiteralPropertyName *ast); - - // array literals - virtual bool visit(QDeclarativeJS::AST::ElementList *ast); - virtual bool visit(QDeclarativeJS::AST::Elision *ast); - - // function calls - virtual bool visit(QDeclarativeJS::AST::ArgumentList *ast); - - // expressions - virtual bool visit(QDeclarativeJS::AST::ObjectLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::ArrayLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::ThisExpression *ast); - virtual bool visit(QDeclarativeJS::AST::IdentifierExpression *ast); - virtual bool visit(QDeclarativeJS::AST::NullExpression *ast); - virtual bool visit(QDeclarativeJS::AST::TrueLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::FalseLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::StringLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::NumericLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::RegExpLiteral *ast); - virtual bool visit(QDeclarativeJS::AST::NestedExpression *ast); - virtual bool visit(QDeclarativeJS::AST::ArrayMemberExpression *ast); - virtual bool visit(QDeclarativeJS::AST::FieldMemberExpression *ast); - virtual bool visit(QDeclarativeJS::AST::NewMemberExpression *ast); - virtual bool visit(QDeclarativeJS::AST::NewExpression *ast); - virtual bool visit(QDeclarativeJS::AST::CallExpression *ast); - virtual bool visit(QDeclarativeJS::AST::PostIncrementExpression *ast); - virtual bool visit(QDeclarativeJS::AST::PostDecrementExpression *ast); - virtual bool visit(QDeclarativeJS::AST::DeleteExpression *ast); - virtual bool visit(QDeclarativeJS::AST::VoidExpression *ast); - virtual bool visit(QDeclarativeJS::AST::TypeOfExpression *ast); - virtual bool visit(QDeclarativeJS::AST::PreIncrementExpression *ast); - virtual bool visit(QDeclarativeJS::AST::PreDecrementExpression *ast); - virtual bool visit(QDeclarativeJS::AST::UnaryPlusExpression *ast); - virtual bool visit(QDeclarativeJS::AST::UnaryMinusExpression *ast); - virtual bool visit(QDeclarativeJS::AST::TildeExpression *ast); - virtual bool visit(QDeclarativeJS::AST::NotExpression *ast); - virtual bool visit(QDeclarativeJS::AST::BinaryExpression *ast); - virtual bool visit(QDeclarativeJS::AST::ConditionalExpression *ast); - virtual bool visit(QDeclarativeJS::AST::Expression *ast); - - // statements - virtual bool visit(QDeclarativeJS::AST::Block *ast); - virtual bool visit(QDeclarativeJS::AST::StatementList *ast); - virtual bool visit(QDeclarativeJS::AST::VariableStatement *ast); - virtual bool visit(QDeclarativeJS::AST::VariableDeclarationList *ast); - virtual bool visit(QDeclarativeJS::AST::VariableDeclaration *ast); - virtual bool visit(QDeclarativeJS::AST::EmptyStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ExpressionStatement *ast); - virtual bool visit(QDeclarativeJS::AST::IfStatement *ast); - virtual bool visit(QDeclarativeJS::AST::DoWhileStatement *ast); - virtual bool visit(QDeclarativeJS::AST::WhileStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ForStatement *ast); - virtual bool visit(QDeclarativeJS::AST::LocalForStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ForEachStatement *ast); - virtual bool visit(QDeclarativeJS::AST::LocalForEachStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ContinueStatement *ast); - virtual bool visit(QDeclarativeJS::AST::BreakStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ReturnStatement *ast); - virtual bool visit(QDeclarativeJS::AST::WithStatement *ast); - virtual bool visit(QDeclarativeJS::AST::SwitchStatement *ast); - virtual bool visit(QDeclarativeJS::AST::CaseBlock *ast); - virtual bool visit(QDeclarativeJS::AST::CaseClauses *ast); - virtual bool visit(QDeclarativeJS::AST::CaseClause *ast); - virtual bool visit(QDeclarativeJS::AST::DefaultClause *ast); - virtual bool visit(QDeclarativeJS::AST::LabelledStatement *ast); - virtual bool visit(QDeclarativeJS::AST::ThrowStatement *ast); - virtual bool visit(QDeclarativeJS::AST::TryStatement *ast); - virtual bool visit(QDeclarativeJS::AST::Catch *ast); - virtual bool visit(QDeclarativeJS::AST::Finally *ast); - virtual bool visit(QDeclarativeJS::AST::FunctionDeclaration *ast); - virtual bool visit(QDeclarativeJS::AST::FunctionExpression *ast); - virtual bool visit(QDeclarativeJS::AST::FormalParameterList *ast); - virtual bool visit(QDeclarativeJS::AST::FunctionBody *ast); - virtual bool visit(QDeclarativeJS::AST::DebuggerStatement *ast); - -private: - bool buildName(QList<QStringRef> &name, QDeclarativeJS::AST::Node *node, - QList<QDeclarativeJS::AST::ExpressionNode *> *nodes); - void discard(); - - const QV4Compiler::Expression *m_expression; - QDeclarativeEnginePrivate *m_engine; - - QDeclarativeJS::IR::Function *_function; - QDeclarativeJS::IR::BasicBlock *_block; - bool _discard; - - ExprResult _expr; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4IRBUILDER_P_H diff --git a/src/declarative/qml/v4/qv4program_p.h b/src/declarative/qml/v4/qv4program_p.h deleted file mode 100644 index 6792ccb783..0000000000 --- a/src/declarative/qml/v4/qv4program_p.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4PROGRAM_P_H -#define QV4PROGRAM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qv4instruction_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -struct QV4Program { - quint32 bindings; - quint32 dataLength; - quint32 signalTableOffset; - quint32 exceptionDataOffset; - quint16 subscriptions; - quint16 identifiers; - quint16 instructionCount; - - struct BindingReference { - quint32 binding; - quint32 blockMask; - }; - - struct BindingReferenceList { - quint32 count; - BindingReference bindings[]; - }; - - inline const char *data() const; - inline const char *instructions() const; - inline BindingReferenceList *signalTable(int signalIndex) const; -}; - -enum QDeclarativeRegisterType { - UndefinedType, - QObjectStarType, - QRealType, - IntType, - BoolType, - - PODValueType, - - FirstCleanupType, - QStringType = FirstCleanupType, - QUrlType, - QVariantType, - QColorType -}; - -const char *QV4Program::data() const -{ - return ((const char *)this) + sizeof(QV4Program); -} - -const char *QV4Program::instructions() const -{ - return (const char *)(data() + dataLength); -} - -QV4Program::BindingReferenceList *QV4Program::signalTable(int signalIndex) const -{ - quint32 *signalTable = (quint32 *)(data() + signalTableOffset); - return (BindingReferenceList *)(signalTable + signalTable[signalIndex]); -} - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QV4PROGRAM_P_H - diff --git a/src/declarative/qml/v4/v4.pri b/src/declarative/qml/v4/v4.pri deleted file mode 100644 index b6784851d8..0000000000 --- a/src/declarative/qml/v4/v4.pri +++ /dev/null @@ -1,15 +0,0 @@ -HEADERS += \ - $$PWD/qv4compiler_p.h \ - $$PWD/qv4compiler_p_p.h \ - $$PWD/qv4ir_p.h \ - $$PWD/qv4irbuilder_p.h \ - $$PWD/qv4instruction_p.h \ - $$PWD/qv4bindings_p.h \ - $$PWD/qv4program_p.h \ - -SOURCES += \ - $$PWD/qv4compiler.cpp \ - $$PWD/qv4ir.cpp \ - $$PWD/qv4irbuilder.cpp \ - $$PWD/qv4instruction.cpp \ - $$PWD/qv4bindings.cpp \ |