diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2012-04-11 14:56:22 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2012-04-11 16:05:03 +0200 |
commit | a896d4b39ec3d45ba708d9b36ea9c864b1df2136 (patch) | |
tree | 45cfe153cce6114c2c76c48dc0bdabde2a8cf3e3 /src/qml/qml/v4 | |
parent | 24fb8dc27eddfdd62bd2c3a6e863cbf433762cd6 (diff) | |
parent | 65bfc35429e845cf6b76d58107360a1360a654fc (diff) |
Merge remote-tracking branch 'origin/master' into api_changes
Conflicts:
src/qml/debugger/qqmlprofilerservice_p.h
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/v4/qv4bindings.cpp
src/quick/items/qquickshadereffect.cpp
src/quick/particles/qquickcustomparticle.cpp
src/quick/qtquick2.cpp
Change-Id: Ia9c6517035ae912fa75e77473a452bd3383def56
Diffstat (limited to 'src/qml/qml/v4')
-rw-r--r-- | src/qml/qml/v4/qv4bindings.cpp | 456 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4bindings_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4compiler.cpp | 267 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4compiler_p_p.h | 16 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4instruction.cpp | 130 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4instruction_p.h | 85 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4ir.cpp | 37 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4ir_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4irbuilder.cpp | 30 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4irbuilder_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4program_p.h | 4 |
11 files changed, 540 insertions, 501 deletions
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 0cd6ffd082..4c92598c32 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -52,6 +52,7 @@ #include <private/qqmlmetatype_p.h> #include <private/qqmltrace_p.h> #include <private/qqmlstringconverters_p.h> +#include <private/qqmlproperty_p.h> #include <QtQml/qqmlinfo.h> #include <QtCore/qnumeric.h> @@ -66,46 +67,53 @@ namespace { struct Register { typedef QQmlRegisterType Type; - void setUndefined() { dataType = UndefinedType; } - void setNull() { dataType = NullType; } - void setNaN() { setqreal(qSNaN()); } - bool isUndefined() const { return dataType == UndefinedType; } + inline void setUndefined() { dataType = UndefinedType; } + inline void setNull() { dataType = NullType; } + inline void setNaN() { setnumber(qSNaN()); } + inline bool isUndefined() const { return dataType == UndefinedType; } - void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; } - QObject *getQObject() const { return qobjectValue; } + inline void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; } + inline QObject *getQObject() const { return qobjectValue; } - void setqreal(qreal v) { qrealValue = v; dataType = QRealType; } - qreal getqreal() const { return qrealValue; } - qreal &getqrealref() { return qrealValue; } + inline void setnumber(double v) { numberValue = v; dataType = NumberType; } + inline double getnumber() const { return numberValue; } + inline double &getnumberref() { return numberValue; } - void setint(int v) { intValue = v; dataType = IntType; } - int getint() const { return intValue; } - int &getintref() { return intValue; } + inline void setfloat(float v) { floatValue = v; dataType = FloatType; } + inline float getfloat() const { return floatValue; } + inline float &getfloatref() { return floatValue; } - void setbool(bool v) { boolValue = v; dataType = BoolType; } - bool getbool() const { return boolValue; } - bool &getboolref() { return boolValue; } + inline void setint(int v) { intValue = v; dataType = IntType; } + inline int getint() const { return intValue; } + inline int &getintref() { return intValue; } - QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } - QString *getstringptr() { return (QString *)typeDataPtr(); } - QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } - const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } - const QString *getstringptr() const { return (QString *)typeDataPtr(); } - const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } + inline void setbool(bool v) { boolValue = v; dataType = BoolType; } + inline bool getbool() const { return boolValue; } + inline bool &getboolref() { return boolValue; } + + inline QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } + inline QString *getstringptr() { return (QString *)typeDataPtr(); } + inline QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } + inline QColor *getcolorptr() { return (QColor *)typeDataPtr(); } + inline const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } + inline const QString *getstringptr() const { return (QString *)typeDataPtr(); } + inline const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } + inline const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); } size_t dataSize() { return sizeof(data); } - void *typeDataPtr() { return (void *)&data; } - void *typeMemory() { return (void *)data; } - const void *typeDataPtr() const { return (void *)&data; } - const void *typeMemory() const { return (void *)data; } + inline void *typeDataPtr() { return (void *)&data; } + inline void *typeMemory() { return (void *)data; } + inline const void *typeDataPtr() const { return (void *)&data; } + inline const void *typeMemory() const { return (void *)data; } - Type gettype() const { return dataType; } - void settype(Type t) { dataType = t; } + inline Type gettype() const { return dataType; } + inline void settype(Type t) { dataType = t; } Type dataType; // Type of data union { QObject *qobjectValue; - qreal qrealValue; + double numberValue; + float floatValue; int intValue; bool boolValue; void *data[sizeof(QVariant)]; @@ -387,85 +395,6 @@ void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex) 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, QQmlContextData *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; @@ -529,10 +458,29 @@ static void testBindingResult(const QString &binding, int line, int column, if (expression.hasError()) { iserror = true; qtscriptResult = "exception"; - } else { - qtscriptResult = testResultToString(value, isUndefined); + } else if (value.userType() != resultType) { + // Override the QMetaType conversions to make them more JS friendly. + if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString || + resultType == QMetaType::QUrl)) { + // number to string-like conversion. + value = QVariant::fromValue<QString>(QString::number(value.toDouble(), 'g', 16)); + } else if (value.userType() == QMetaType::QUrl && resultType == QMetaType::Bool) { + // url to bool conversion + value = QVariant::fromValue<bool>(!value.toUrl().isEmpty()); + } + + if (!value.isNull() && !value.convert(resultType)) { + iserror = true; + qtscriptResult = "exception"; + } else if (resultType == QMetaType::QUrl) { + // a V8 value was converted to QUrl. + value = QVariant::fromValue<QUrl>(context->resolvedUrl(value.toUrl())); + } } + if (! iserror) + qtscriptResult = testResultToString(value, isUndefined); + if (isUndefined && result.isUndefined()) { return; } else if(isUndefined != result.isUndefined()) { @@ -557,8 +505,8 @@ static void testBindingResult(const QString &binding, int line, int column, case QMetaType::Int: v4value = result.getint(); break; - case QMetaType::QReal: - v4value = result.getqreal(); + case QMetaType::Double: + v4value = result.getnumber(); break; default: if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { @@ -621,15 +569,15 @@ static void throwException(int id, QQmlDelayedError *error, QQmlEnginePrivate::warning(context->engine, error->error); } -const qreal QV4Bindings::D32 = 4294967296.0; +const double QV4Bindings::D32 = 4294967296.0; -qint32 QV4Bindings::toInt32(qreal n) +qint32 QV4Bindings::toInt32(double n) { if (qIsNaN(n) || qIsInf(n) || (n == 0)) return 0; double sign = (n < 0) ? -1.0 : 1.0; - qreal abs_n = fabs(n); + double abs_n = fabs(n); n = ::fmod(sign * ::floor(abs_n), D32); const double D31 = D32 / 2.0; @@ -643,13 +591,13 @@ qint32 QV4Bindings::toInt32(qreal n) return qint32 (n); } -inline quint32 QV4Bindings::toUint32(qreal n) +inline quint32 QV4Bindings::toUint32(double n) { if (qIsNaN(n) || qIsInf(n) || (n == 0)) return 0; double sign = (n < 0) ? -1.0 : 1.0; - qreal abs_n = fabs(n); + double abs_n = fabs(n); n = ::fmod(sign * ::floor(abs_n), D32); @@ -665,6 +613,11 @@ inline quint32 QV4Bindings::toUint32(qreal n) goto exceptionExit; \ } +#define THROW_VALUE_EXCEPTION_STR(id, str) { \ + throwException((id), error, program, context, (str)); \ + goto exceptionExit; \ +} + #define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString()) #define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg)) @@ -791,13 +744,21 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, sub->bindings = this; sub->method = subIdx; } - reg.init((Register::Type)instr->fetchAndSubscribe.valueType); + + const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType; + reg.init(valueType); if (instr->fetchAndSubscribe.valueType >= FirstCleanupType) MARK_REGISTER(instr->fetchAndSubscribe.reg); QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors; accessors->read(object, instr->fetchAndSubscribe.property.accessorData, reg.typeDataPtr()); + if (valueType == FloatType) { + // promote floats + const double v = reg.getfloat(); + reg.setnumber(v); + } + if (accessors->notifier) { QQmlNotifier *notifier = 0; accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier); @@ -868,11 +829,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(UnaryNot, unaryop) - QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop) + QML_V4_BEGIN_INSTR(UnaryMinusNumber, unaryop) { - registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal()); + registers[instr->unaryop.output].setnumber(-registers[instr->unaryop.src].getnumber()); } - QML_V4_END_INSTR(UnaryMinusReal, unaryop) + QML_V4_END_INSTR(UnaryMinusNumber, unaryop) QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop) { @@ -880,11 +841,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(UnaryMinusInt, unaryop) - QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop) + QML_V4_BEGIN_INSTR(UnaryPlusNumber, unaryop) { - registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal()); + registers[instr->unaryop.output].setnumber(+registers[instr->unaryop.src].getnumber()); } - QML_V4_END_INSTR(UnaryPlusReal, unaryop) + QML_V4_END_INSTR(UnaryPlusNumber, unaryop) QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop) { @@ -901,14 +862,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(ConvertBoolToInt, unaryop) - QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertBoolToNumber, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); - else output.setqreal(src.getbool()); + else output.setnumber(src.getbool()); } - QML_V4_END_INSTR(ConvertBoolToReal, unaryop) + QML_V4_END_INSTR(ConvertBoolToNumber, unaryop) QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop) { @@ -932,14 +893,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(ConvertIntToBool, unaryop) - QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertIntToNumber, 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())); + else output.setnumber(double(src.getint())); } - QML_V4_END_INSTR(ConvertIntToReal, unaryop) + QML_V4_END_INSTR(ConvertIntToNumber, unaryop) QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop) { @@ -954,25 +915,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(ConvertIntToString, unaryop) - QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop) + QML_V4_BEGIN_INSTR(ConvertNumberToBool, 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); + else output.setbool(src.getnumber() != 0); } - QML_V4_END_INSTR(ConvertRealToBool, unaryop) + QML_V4_END_INSTR(ConvertNumberToBool, unaryop) - QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop) + QML_V4_BEGIN_INSTR(ConvertNumberToInt, 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())); + else output.setint(toInt32(src.getnumber())); } - QML_V4_END_INSTR(ConvertRealToInt, unaryop) + QML_V4_END_INSTR(ConvertNumberToInt, unaryop) - QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop) + QML_V4_BEGIN_INSTR(ConvertNumberToString, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -980,11 +941,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, if (src.isUndefined()) { output.setUndefined(); } else { - new (output.getstringptr()) QString(QString::number(src.getqreal())); + new (output.getstringptr()) QString(QString::number(src.getnumber(), 'g', 16)); STRING_REGISTER(instr->unaryop.output); } } - QML_V4_END_INSTR(ConvertRealToString, unaryop) + QML_V4_END_INSTR(ConvertNumberToString, unaryop) QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop) { @@ -1026,7 +987,7 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(ConvertStringToInt, unaryop) - QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertStringToNumber, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -1041,10 +1002,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, output.cleanupString(); MARK_CLEAN_REGISTER(instr->unaryop.output); } - output.setqreal(tmp.toNumber()); + output.setnumber(tmp.toNumber()); } } - QML_V4_END_INSTR(ConvertStringToReal, unaryop) + QML_V4_END_INSTR(ConvertStringToNumber, unaryop) QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop) { @@ -1190,75 +1151,75 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(ResolveUrl, unaryop) - QML_V4_BEGIN_INSTR(MathSinReal, unaryop) + QML_V4_BEGIN_INSTR(MathSinNumber, 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())); + else output.setnumber(qSin(src.getnumber())); } - QML_V4_END_INSTR(MathSinReal, unaryop) + QML_V4_END_INSTR(MathSinNumber, unaryop) - QML_V4_BEGIN_INSTR(MathCosReal, unaryop) + QML_V4_BEGIN_INSTR(MathCosNumber, 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())); + else output.setnumber(qCos(src.getnumber())); } - QML_V4_END_INSTR(MathCosReal, unaryop) + QML_V4_END_INSTR(MathCosNumber, unaryop) - QML_V4_BEGIN_INSTR(MathAbsReal, unaryop) + QML_V4_BEGIN_INSTR(MathAbsNumber, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); - else output.setqreal(qAbs(src.getqreal())); + else output.setnumber(qAbs(src.getnumber())); } - QML_V4_END_INSTR(MathAbsReal, unaryop) + QML_V4_END_INSTR(MathAbsNumber, unaryop) - QML_V4_BEGIN_INSTR(MathRoundReal, unaryop) + QML_V4_BEGIN_INSTR(MathRoundNumber, 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())); + else output.setint(qRound(src.getnumber())); } - QML_V4_END_INSTR(MathRoundReal, unaryop) + QML_V4_END_INSTR(MathRoundNumber, unaryop) - QML_V4_BEGIN_INSTR(MathFloorReal, unaryop) + QML_V4_BEGIN_INSTR(MathFloorNumber, 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())); + else output.setint(qFloor(src.getnumber())); } - QML_V4_END_INSTR(MathFloorReal, unaryop) + QML_V4_END_INSTR(MathFloorNumber, unaryop) - QML_V4_BEGIN_INSTR(MathCeilReal, unaryop) + QML_V4_BEGIN_INSTR(MathCeilNumber, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); - else output.setint(qCeil(src.getqreal())); + else output.setint(qCeil(src.getnumber())); } - QML_V4_END_INSTR(MathCeilReal, unaryop) + QML_V4_END_INSTR(MathCeilNumber, unaryop) - QML_V4_BEGIN_INSTR(MathPIReal, unaryop) + QML_V4_BEGIN_INSTR(MathPINumber, unaryop) { - static const qreal qmlPI = 2.0 * qAsin(1.0); + static const double qmlPI = 2.0 * qAsin(1.0); Register &output = registers[instr->unaryop.output]; - output.setqreal(qmlPI); + output.setnumber(qmlPI); } - QML_V4_END_INSTR(MathPIReal, unaryop) + QML_V4_END_INSTR(MathPINumber, unaryop) QML_V4_BEGIN_INSTR(LoadNull, null_value) registers[instr->null_value.reg].setNull(); QML_V4_END_INSTR(LoadNull, null_value) - 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(LoadNumber, number_value) + registers[instr->number_value.reg].setnumber(instr->number_value.value); + QML_V4_END_INSTR(LoadNumber, number_value) QML_V4_BEGIN_INSTR(LoadInt, int_value) registers[instr->int_value.reg].setint(instr->int_value.value); @@ -1305,12 +1266,12 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(BitXorInt, binaryop) - QML_V4_BEGIN_INSTR(AddReal, binaryop) + QML_V4_BEGIN_INSTR(AddNumber, binaryop) { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() + + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(AddReal, binaryop) + QML_V4_END_INSTR(AddNumber, binaryop) QML_V4_BEGIN_INSTR(AddString, binaryop) { @@ -1324,36 +1285,33 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(AddString, binaryop) - QML_V4_BEGIN_INSTR(SubReal, binaryop) + QML_V4_BEGIN_INSTR(SubNumber, binaryop) { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() - + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(SubReal, binaryop) + QML_V4_END_INSTR(SubNumber, binaryop) - QML_V4_BEGIN_INSTR(MulReal, binaryop) + QML_V4_BEGIN_INSTR(MulNumber, binaryop) { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() * + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(MulReal, binaryop) + QML_V4_END_INSTR(MulNumber, binaryop) - QML_V4_BEGIN_INSTR(DivReal, binaryop) + QML_V4_BEGIN_INSTR(DivNumber, binaryop) { - registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() / + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(DivReal, binaryop) + QML_V4_END_INSTR(DivNumber, binaryop) - QML_V4_BEGIN_INSTR(ModReal, binaryop) + QML_V4_BEGIN_INSTR(ModNumber, 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())); + target.setnumber(::fmod(left.getnumber(), right.getnumber())); } QML_V4_END_INSTR(ModInt, binaryop) @@ -1378,61 +1336,61 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(URShiftInt, binaryop) - QML_V4_BEGIN_INSTR(GtReal, binaryop) + QML_V4_BEGIN_INSTR(GtNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() > + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(GtReal, binaryop) + QML_V4_END_INSTR(GtNumber, binaryop) - QML_V4_BEGIN_INSTR(LtReal, binaryop) + QML_V4_BEGIN_INSTR(LtNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() < + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(LtReal, binaryop) + QML_V4_END_INSTR(LtNumber, binaryop) - QML_V4_BEGIN_INSTR(GeReal, binaryop) + QML_V4_BEGIN_INSTR(GeNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >= + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(GeReal, binaryop) + QML_V4_END_INSTR(GeNumber, binaryop) - QML_V4_BEGIN_INSTR(LeReal, binaryop) + QML_V4_BEGIN_INSTR(LeNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <= + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(LeReal, binaryop) + QML_V4_END_INSTR(LeNumber, binaryop) - QML_V4_BEGIN_INSTR(EqualReal, binaryop) + QML_V4_BEGIN_INSTR(EqualNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() == + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(EqualReal, binaryop) + QML_V4_END_INSTR(EqualNumber, binaryop) - QML_V4_BEGIN_INSTR(NotEqualReal, binaryop) + QML_V4_BEGIN_INSTR(NotEqualNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() != + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(NotEqualReal, binaryop) + QML_V4_END_INSTR(NotEqualNumber, binaryop) - QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop) + QML_V4_BEGIN_INSTR(StrictEqualNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() == + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(StrictEqualReal, binaryop) + QML_V4_END_INSTR(StrictEqualNumber, binaryop) - QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop) + QML_V4_BEGIN_INSTR(StrictNotEqualNumber, binaryop) { - registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != - registers[instr->binaryop.right].getqreal()); + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() != + registers[instr->binaryop.right].getnumber()); } - QML_V4_END_INSTR(StrictNotEqualReal, binaryop) + QML_V4_END_INSTR(StrictNotEqualNumber, binaryop) QML_V4_BEGIN_INSTR(GtString, binaryop) { @@ -1578,25 +1536,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(StrictNotEqualObject, binaryop) - QML_V4_BEGIN_INSTR(MathMaxReal, binaryop) + QML_V4_BEGIN_INSTR(MathMaxNumber, binaryop) { const Register &left = registers[instr->binaryop.left]; const Register &right = registers[instr->binaryop.right]; Register &output = registers[instr->binaryop.output]; if (left.isUndefined() || right.isUndefined()) output.setUndefined(); - else output.setqreal(qMax(left.getqreal(), right.getqreal())); + else output.setnumber(qMax(left.getnumber(), right.getnumber())); } - QML_V4_END_INSTR(MathMaxReal, binaryop) + QML_V4_END_INSTR(MathMaxNumber, binaryop) - QML_V4_BEGIN_INSTR(MathMinReal, binaryop) + QML_V4_BEGIN_INSTR(MathMinNumber, binaryop) { const Register &left = registers[instr->binaryop.left]; const Register &right = registers[instr->binaryop.right]; Register &output = registers[instr->binaryop.output]; if (left.isUndefined() || right.isUndefined()) output.setUndefined(); - else output.setqreal(qMin(left.getqreal(), right.getqreal())); + else output.setnumber(qMin(left.getnumber(), right.getnumber())); } - QML_V4_END_INSTR(MathMinReal, binaryop) + QML_V4_END_INSTR(MathMinNumber, binaryop) QML_V4_BEGIN_INSTR(NewString, construct) { @@ -1625,11 +1583,17 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, if (!object) { THROW_EXCEPTION(instr->fetch.exceptionId); } else { - reg.init((Register::Type)instr->fetch.valueType); + const Register::Type valueType = (Register::Type)instr->fetch.valueType; + reg.init(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); + if (valueType == FloatType) { + // promote floats + const double v = reg.getfloat(); + reg.setnumber(v); + } } } QML_V4_END_INSTR(Fetch, fetch) @@ -1649,6 +1613,30 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, if (data.isUndefined()) THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value")); + if (data.gettype() == QObjectStarType) { + if (QObject *dataObject = data.getQObject()) { + const QMetaObject *dataMo = dataObject->metaObject(); + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + QMetaProperty receiver = output->metaObject()->property(instr->store.index); + const QMetaObject *receiverMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, receiver.userType()); + + // Verify that these types are compatible + if (!QQmlPropertyPrivate::canConvert(dataMo, receiverMo)) { + THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") + + QLatin1String(dataMo->className()) + + QLatin1String(" to ") + + QLatin1String(receiverMo->className())); + } + } + } + + if (instr->store.valueType == FloatType) { + // cast numbers to floats + const float v = (float) data.getnumber(); + data.setfloat(v); + } + int status = -1; void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; QMetaObject::metacall(output, QMetaObject::WriteProperty, @@ -1687,22 +1675,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, 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) + QML_V4_BEGIN_INSTR(Throw, throwop) + THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr()); + QML_V4_END_INSTR(Throw, throwop) + #ifdef QML_THREADED_INTERPRETER // nothing to do #else diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h index 1824fa4ee9..3a7d175d7b 100644 --- a/src/qml/qml/v4/qv4bindings_p.h +++ b/src/qml/qml/v4/qv4bindings_p.h @@ -141,9 +141,9 @@ private: inline void subscribeId(QQmlContextData *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); + inline static qint32 toInt32(double n); + static const double D32; + static quint32 toUint32(double n); }; diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index c9495e8987..045a14fbb5 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -62,7 +62,9 @@ static bool qmlEnableV4 = true; using namespace QQmlJS; QV4CompilerPrivate::QV4CompilerPrivate() - : _function(0) , _block(0) , _discarded(false), registerCount(0) + : subscriptionOffset(0) + , _function(0) , _block(0) , _discarded(false), registerCount(0) + , bindingLine(0), bindingColumn(0) { } @@ -73,6 +75,8 @@ void QV4CompilerPrivate::trace(int line, int column) { bytecode.clear(); + this->bindingLine = line; + this->bindingColumn = column; this->currentReg = _function->tempCount; this->registerCount = qMax(this->registerCount, this->currentReg); @@ -226,8 +230,9 @@ void QV4CompilerPrivate::visitConst(IR::Const *e) gen(i); } break; - case IR::RealType: { - Instr::LoadReal i; + case IR::FloatType: + case IR::NumberType: { + Instr::LoadNumber i; i.reg = currentReg; i.value = e->value; gen(i); @@ -316,7 +321,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e) Instr::LoadAttached attached; attached.output = currentReg; attached.reg = currentReg; - attached.exceptionId = exceptionId(e->line, e->column); + attached.exceptionId = exceptionId(bindingLine, bindingColumn); if (e->declarativeType->attachedPropertiesId() == -1) discard(); attached.id = e->declarativeType->attachedPropertiesId(); @@ -351,8 +356,11 @@ void QV4CompilerPrivate::visitName(IR::Name *e) QQmlRegisterType regType; switch (propTy) { - case QMetaType::QReal: - regType = QRealType; + case QMetaType::Float: + regType = FloatType; + break; + case QMetaType::Double: + regType = NumberType; break; case QMetaType::Bool: regType = BoolType; @@ -373,7 +381,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e) default: if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { regType = PODValueType; - } else if (QQmlMetaType::isQObject(propTy)) { + } else if (engine->metaObjectForType(propTy)) { regType = QObjectStarType; } else { if (qmlVerboseCompiler()) @@ -458,14 +466,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e) } break; case IR::OpUMinus: - if (e->expr->type == IR::RealType) { - Instr::UnaryMinusReal i; + if (IR::isRealType(e->expr->type)) { + Instr::UnaryMinusNumber i; i.output = currentReg; i.src = src; gen(i); } else if (e->expr->type == IR::IntType) { - convertToReal(e->expr, currentReg); - Instr::UnaryMinusReal i; + convertToNumber(e->expr, currentReg); + Instr::UnaryMinusNumber i; i.output = currentReg; i.src = src; gen(i); @@ -475,14 +483,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e) break; case IR::OpUPlus: - if (e->expr->type == IR::RealType) { - Instr::UnaryPlusReal i; + if (IR::isRealType(e->expr->type)) { + Instr::UnaryPlusNumber i; i.output = currentReg; i.src = src; gen(i); } else if (e->expr->type == IR::IntType) { - convertToReal(e->expr, currentReg); - Instr::UnaryPlusReal i; + convertToNumber(e->expr, currentReg); + Instr::UnaryPlusNumber i; i.output = currentReg; i.src = src; gen(i); @@ -522,25 +530,26 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e) } // switch } -void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg) +void QV4CompilerPrivate::convertToNumber(IR::Expr *expr, int reg) { - if (expr->type == IR::RealType) + if (expr->type == IR::NumberType) return; switch (expr->type) { case IR::BoolType: { - Instr::ConvertBoolToReal i; + Instr::ConvertBoolToNumber i; i.output = i.src = reg; gen(i); } break; case IR::IntType: { - Instr::ConvertIntToReal i; + Instr::ConvertIntToNumber i; i.output = i.src = reg; gen(i); } break; - case IR::RealType: + case IR::FloatType: + case IR::NumberType: // nothing to do return; @@ -566,8 +575,9 @@ void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg) // nothing to do return; - case IR::RealType: { - Instr::ConvertRealToInt i; + case IR::FloatType: + case IR::NumberType: { + Instr::ConvertNumberToInt i; i.output = i.src = reg; gen(i); } break; @@ -594,8 +604,9 @@ void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg) gen(i); } break; - case IR::RealType: { - Instr::ConvertRealToBool i; + case IR::FloatType: + case IR::NumberType: { + Instr::ConvertNumberToBool i; i.output = i.src = reg; gen(i); } return; @@ -643,19 +654,19 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e) case IR::OpAdd: if (e->type == IR::StringType) return V4Instr::AddString; - return V4Instr::AddReal; + return V4Instr::AddNumber; case IR::OpSub: - return V4Instr::SubReal; + return V4Instr::SubNumber; case IR::OpMul: - return V4Instr::MulReal; + return V4Instr::MulNumber; case IR::OpDiv: - return V4Instr::DivReal; + return V4Instr::DivNumber; case IR::OpMod: - return V4Instr::ModReal; + return V4Instr::ModNumber; case IR::OpLShift: return V4Instr::LShiftInt; @@ -669,50 +680,50 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e) case IR::OpGt: if (e->left->type == IR::StringType) return V4Instr::GtString; - return V4Instr::GtReal; + return V4Instr::GtNumber; case IR::OpLt: if (e->left->type == IR::StringType) return V4Instr::LtString; - return V4Instr::LtReal; + return V4Instr::LtNumber; case IR::OpGe: if (e->left->type == IR::StringType) return V4Instr::GeString; - return V4Instr::GeReal; + return V4Instr::GeNumber; case IR::OpLe: if (e->left->type == IR::StringType) return V4Instr::LeString; - return V4Instr::LeReal; + return V4Instr::LeNumber; case IR::OpEqual: if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) return V4Instr::EqualObject; if (e->left->type == IR::StringType) return V4Instr::EqualString; - return V4Instr::EqualReal; + return V4Instr::EqualNumber; case IR::OpNotEqual: if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) return V4Instr::NotEqualObject; if (e->left->type == IR::StringType) return V4Instr::NotEqualString; - return V4Instr::NotEqualReal; + return V4Instr::NotEqualNumber; case IR::OpStrictEqual: if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) return V4Instr::StrictEqualObject; if (e->left->type == IR::StringType) return V4Instr::StrictEqualString; - return V4Instr::StrictEqualReal; + return V4Instr::StrictEqualNumber; case IR::OpStrictNotEqual: if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) return V4Instr::StrictNotEqualObject; if (e->left->type == IR::StringType) return V4Instr::StrictNotEqualString; - return V4Instr::StrictNotEqualReal; + return V4Instr::StrictNotEqualNumber; case IR::OpAnd: case IR::OpOr: @@ -733,12 +744,26 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) int left = currentReg; int right = currentReg + 1; - traceExpression(e->left, left); - traceExpression(e->right, right); + if (e->left->asTemp() && e->type != IR::StringType) + left = e->left->asTemp()->index; + else + traceExpression(e->left, left); - // At this point it is possible that the type of the - // subexpressions is different. This can happen because - // we keep BINOP expressions in HIR. + 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: @@ -766,8 +791,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) case IR::OpAdd: if (e->type != IR::StringType) { - convertToReal(e->left, left); - convertToReal(e->right, right); + convertToNumber(e->left, left); + convertToNumber(e->right, right); } break; @@ -775,8 +800,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) case IR::OpMul: case IR::OpDiv: case IR::OpMod: - convertToReal(e->left, left); - convertToReal(e->right, right); + convertToNumber(e->left, left); + convertToNumber(e->right, right); break; case IR::OpGt: @@ -788,8 +813,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) case IR::OpStrictEqual: case IR::OpStrictNotEqual: if (e->left->type >= IR::FirstNumberType) { - convertToReal(e->left, left); - convertToReal(e->right, right); + convertToNumber(e->left, left); + convertToNumber(e->right, right); } break; @@ -813,7 +838,7 @@ 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) { + if (arg != 0 && IR::isRealType(arg->type)) { traceExpression(arg, currentReg); switch (name->builtin) { @@ -821,37 +846,37 @@ void QV4CompilerPrivate::visitCall(IR::Call *call) break; case IR::MathSinBultinFunction: { - Instr::MathSinReal i; + Instr::MathSinNumber i; i.output = i.src = currentReg; gen(i); } return; case IR::MathCosBultinFunction: { - Instr::MathCosReal i; + Instr::MathCosNumber i; i.output = i.src = currentReg; gen(i); } return; case IR::MathAbsBuiltinFunction: { - Instr::MathAbsReal i; + Instr::MathAbsNumber i; i.output = i.src = currentReg; gen(i); } return; case IR::MathRoundBultinFunction: { - Instr::MathRoundReal i; + Instr::MathRoundNumber i; i.output = i.src = currentReg; gen(i); } return; case IR::MathFloorBultinFunction: { - Instr::MathFloorReal i; + Instr::MathFloorNumber i; i.output = i.src = currentReg; gen(i); } return; case IR::MathCeilBuiltinFunction: { - Instr::MathCeilReal i; + Instr::MathCeilNumber i; i.output = i.src = currentReg; gen(i); } return; @@ -869,21 +894,21 @@ void QV4CompilerPrivate::visitCall(IR::Call *call) IR::Expr *arg1 = call->args->expr; IR::Expr *arg2 = call->args->next->expr; - if (arg1 != 0 && arg1->type == IR::RealType && - arg2 != 0 && arg2->type == IR::RealType) { + if (arg1 != 0 && IR::isRealType(arg1->type) && + arg2 != 0 && IR::isRealType(arg2->type)) { traceExpression(arg1, currentReg); traceExpression(arg2, currentReg + 1); if (name->builtin == IR::MathMaxBuiltinFunction) { - Instr::MathMaxReal i; + Instr::MathMaxNumber i; i.left = currentReg; i.right = currentReg + 1; i.output = currentReg; gen(i); return; } else if (name->builtin == IR::MathMinBuiltinFunction) { - Instr::MathMinReal i; + Instr::MathMinNumber i; i.left = currentReg; i.right = currentReg + 1; i.output = currentReg; @@ -917,7 +942,17 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) quint8 dest = target->index; - if (target->type != s->source->type) { + IR::Type targetTy = s->target->type; + IR::Type sourceTy = s->source->type; + + // promote the floats + if (sourceTy == IR::FloatType) + sourceTy = IR::NumberType; + + if (targetTy == IR::FloatType) + targetTy = IR::NumberType; + + if (sourceTy != targetTy) { quint8 src = dest; if (IR::Temp *t = s->source->asTemp()) @@ -926,8 +961,6 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) 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) { @@ -937,13 +970,22 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) // url-to-xxx conversions. break; default: { + if (s->isMoveForReturn) { + V4Instr instr; + instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn); + registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2") + .arg(QLatin1String(IR::typeName(sourceTy))) + .arg(QLatin1String(IR::typeName(targetTy))))); + instr.throwop.message = dest; + gen(V4Instr::Throw, instr); + return; + } // generate a UrlToString conversion and fix // the type of the source expression. V4Instr conv; - conv.unaryop.output = V4Instr::ConvertUrlToString; + conv.unaryop.output = src; conv.unaryop.src = src; - gen(opcode, conv); - + gen(V4Instr::ConvertUrlToString, conv); sourceTy = IR::StringType; break; } @@ -953,7 +995,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) if (targetTy == IR::BoolType) { switch (sourceTy) { case IR::IntType: opcode = V4Instr::ConvertIntToBool; break; - case IR::RealType: opcode = V4Instr::ConvertRealToBool; break; + case IR::NumberType: opcode = V4Instr::ConvertNumberToBool; break; case IR::StringType: opcode = V4Instr::ConvertStringToBool; break; case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break; case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break; @@ -963,33 +1005,44 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) } else if (targetTy == IR::IntType) { switch (sourceTy) { case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break; - case IR::RealType: { + case IR::NumberType: { if (s->isMoveForReturn) - opcode = V4Instr::MathRoundReal; + opcode = V4Instr::MathRoundNumber; else - opcode = V4Instr::ConvertRealToInt; + opcode = V4Instr::ConvertNumberToInt; break; } case IR::StringType: opcode = V4Instr::ConvertStringToInt; break; default: break; } // switch - } else if (targetTy == IR::RealType) { + } else if (IR::isRealType(targetTy)) { switch (sourceTy) { - case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break; - case IR::IntType: opcode = V4Instr::ConvertIntToReal; break; - case IR::StringType: opcode = V4Instr::ConvertStringToReal; break; + case IR::BoolType: opcode = V4Instr::ConvertBoolToNumber; break; + case IR::IntType: opcode = V4Instr::ConvertIntToNumber; break; + case IR::StringType: opcode = V4Instr::ConvertStringToNumber; 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::NumberType: opcode = V4Instr::ConvertNumberToString; break; case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break; case IR::ColorType: opcode = V4Instr::ConvertColorToString; break; default: break; } // switch } else if (targetTy == IR::UrlType) { + if (s->isMoveForReturn && sourceTy != IR::StringType) { + V4Instr instr; + instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn); + registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2") + .arg(QLatin1String(IR::typeName(sourceTy))) + .arg(QLatin1String(IR::typeName(targetTy))))); + instr.throwop.message = dest; + gen(V4Instr::Throw, instr); + return; + } + V4Instr convToString; convToString.unaryop.output = dest; convToString.unaryop.src = src; @@ -998,7 +1051,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s) 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::NumberType: gen(V4Instr::ConvertNumberToString, convToString); sourceTy = IR::StringType; break; case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break; default: break; } // switch @@ -1094,8 +1147,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s) case IR::IntType: test.regType = QMetaType::Int; break; - case IR::RealType: - test.regType = QMetaType::QReal; + case IR::FloatType: + case IR::NumberType: + test.regType = QMetaType::Double; break; default: discard(); @@ -1108,6 +1162,7 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s) store.output = 0; store.index = expression->property->index; store.reg = storeReg; + store.valueType = s->type == IR::FloatType ? FloatType : 0; store.exceptionId = exceptionId(s->line, s->column); gen(store); } @@ -1119,7 +1174,6 @@ void QV4Compiler::dump(const QByteArray &programData) 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(); @@ -1137,8 +1191,8 @@ void QV4CompilerPrivate::resetInstanceState() data = committed.data; exceptions = committed.exceptions; usedSubscriptionIds.clear(); - subscriptionIds = committed.subscriptionIds; - registeredStrings = committed.registeredStrings; + subscriptionIds.clear(); + subscriptionOffset = committed.subscriptionCount; bytecode.clear(); patches.clear(); pool.clear(); @@ -1159,8 +1213,9 @@ int QV4CompilerPrivate::commitCompile() committed.bytecode.append(bytecode.constData(), bytecode.size()); committed.data = data; committed.exceptions = exceptions; - committed.subscriptionIds = subscriptionIds; - committed.registeredStrings = registeredStrings; + committed.subscriptionCount = subscriptionOffset + subscriptionIds.count(); + if (bindingsDump()) + committed.subscriptions.append(subscriptionIds); return rv; } @@ -1212,7 +1267,7 @@ bool QV4CompilerPrivate::compile(QQmlJS::AST::Node *node) qerr << endl; } - if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31) + if (discarded || subscriptionIds.count() > 0xFFFF || registerCount > 31) return false; return true; @@ -1236,32 +1291,6 @@ int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str) 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. */ @@ -1285,7 +1314,7 @@ int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub) QString str = sub.join(QLatin1String(".")); int *iter = subscriptionIds.value(str); if (!iter) { - int count = subscriptionIds.count(); + int count = subscriptionOffset + subscriptionIds.count(); iter = &subscriptionIds[str]; *iter = count; } @@ -1384,8 +1413,8 @@ QByteArray QV4CompilerPrivate::buildSignalTable() const QVector<quint32> header; QVector<quint32> data; - for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) { - header.append(committed.subscriptionIds.count() + data.count()); + for (int ii = 0; ii < committed.subscriptionCount; ++ii) { + header.append(committed.subscriptionCount + data.count()); const QList<QPair<int, quint32> > &bindings = table[ii]; data.append(bindings.count()); for (int jj = 0; jj < bindings.count(); ++jj) { @@ -1443,8 +1472,7 @@ QByteArray QV4Compiler::program() const data += d->buildExceptionData(); prog.dataLength = 4 * ((data.size() + 3) / 4); - prog.subscriptions = d->committed.subscriptionIds.count(); - prog.identifiers = d->committed.registeredStrings.count(); + prog.subscriptions = d->committed.subscriptionCount; prog.instructionCount = bytecode.count(); int size = sizeof(QV4Program) + bytecode.count(); size += prog.dataLength; @@ -1461,12 +1489,13 @@ QByteArray QV4Compiler::program() const if (bindingsDump()) { qWarning().nospace() << "Subscription slots:"; - for (QQmlAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin(); - iter != d->committed.subscriptionIds.end(); - ++iter) { - qWarning().nospace() << " " << iter->first << "\t-> " << iter->second; + QQmlAssociationList<QString, int> subscriptionIds; + foreach (subscriptionIds, d->committed.subscriptions) { + for (QQmlAssociationList<QString, int>::ConstIterator iter = subscriptionIds.begin(); + iter != subscriptionIds.end(); ++iter) { + qWarning().nospace() << " " << iter->first << "\t-> " << iter->second; + } } - QV4Compiler::dump(programData); } diff --git a/src/qml/qml/v4/qv4compiler_p_p.h b/src/qml/qml/v4/qv4compiler_p_p.h index a9209d978f..0c06ade87f 100644 --- a/src/qml/qml/v4/qv4compiler_p_p.h +++ b/src/qml/qml/v4/qv4compiler_p_p.h @@ -128,8 +128,6 @@ public: bool compile(QQmlJS::AST::Node *); int registerLiteralString(quint8 reg, const QStringRef &); - int registerString(const QString &); - QQmlAssociationList<QString, QPair<int, int> > registeredStrings; QByteArray data; bool blockNeedsSubscription(const QStringList &); @@ -141,7 +139,7 @@ public: QVector<quint64> exceptions; QQmlAssociationList<int, quint32> usedSubscriptionIds; - + int subscriptionOffset; QQmlAssociationList<QString, int> subscriptionIds; QQmlJS::Bytecode bytecode; @@ -156,17 +154,17 @@ public: QQmlPool pool; // Committed binding data - struct { + struct Committed { + Committed(): subscriptionCount(0) {} QList<int> offsets; QList<QQmlAssociationList<int, quint32> > dependencies; //QQmlJS::Bytecode bytecode; QByteArray bytecode; QByteArray data; - QQmlAssociationList<QString, int> subscriptionIds; QVector<quint64> exceptions; - - QQmlAssociationList<QString, QPair<int, int> > registeredStrings; + int subscriptionCount; + QList<QQmlAssociationList<QString, int> > subscriptions; int count() const { return offsets.count(); } } committed; @@ -174,7 +172,7 @@ public: QByteArray buildSignalTable() const; QByteArray buildExceptionData() const; - void convertToReal(QQmlJS::IR::Expr *expr, int reg); + void convertToNumber(QQmlJS::IR::Expr *expr, int reg); void convertToInt(QQmlJS::IR::Expr *expr, int reg); void convertToBool(QQmlJS::IR::Expr *expr, int reg); quint8 instructionOpcode(QQmlJS::IR::Binop *e); @@ -235,6 +233,8 @@ private: bool usedSubscriptionIdsChanged; quint32 currentBlockMask; + int bindingLine; + int bindingColumn; }; diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp index cb6ff40589..ecd4f01ef3 100644 --- a/src/qml/qml/v4/qv4instruction.cpp +++ b/src/qml/qml/v4/qv4instruction.cpp @@ -123,14 +123,14 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::UnaryMinusNumber: + INSTR_DUMP << "\t" << "UnaryMinusNumber" << "\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 << ")"; + case V4Instr::UnaryPlusNumber: + INSTR_DUMP << "\t" << "UnaryPlusNumber" << "\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 << ")"; @@ -138,8 +138,8 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::ConvertBoolToNumber: + INSTR_DUMP << "\t" << "ConvertBoolToNumber" << "\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 << ")"; @@ -147,20 +147,20 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::ConvertIntToNumber: + INSTR_DUMP << "\t" << "ConvertIntToNumber" << "\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 << ")"; + case V4Instr::ConvertNumberToBool: + INSTR_DUMP << "\t" << "ConvertNumberToBool" << "\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 << ")"; + case V4Instr::ConvertNumberToInt: + INSTR_DUMP << "\t" << "ConvertNumberToInt" << "\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 << ")"; + case V4Instr::ConvertNumberToString: + INSTR_DUMP << "\t" << "ConvertNumberToString" << "\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 << ")"; @@ -168,8 +168,8 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::ConvertStringToNumber: + INSTR_DUMP << "\t" << "ConvertStringToNumber" << "\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 << ")"; @@ -198,32 +198,32 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::MathSinNumber: + INSTR_DUMP << "\t" << "MathSinNumber" << "\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 << ")"; + case V4Instr::MathCosNumber: + INSTR_DUMP << "\t" << "MathCosNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; break; - case V4Instr::MathAbsReal: - INSTR_DUMP << "\t" << "MathAbsReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + case V4Instr::MathAbsNumber: + INSTR_DUMP << "\t" << "MathAbsNumber" << "\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 << ")"; + case V4Instr::MathRoundNumber: + INSTR_DUMP << "\t" << "MathRoundNumber" << "\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 << ")"; + case V4Instr::MathFloorNumber: + INSTR_DUMP << "\t" << "MathFloorNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; break; - case V4Instr::MathCeilReal: - INSTR_DUMP << "\t" << "MathCeilReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + case V4Instr::MathCeilNumber: + INSTR_DUMP << "\t" << "MathCeilNumber" << "\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 << ")"; + case V4Instr::MathPINumber: + INSTR_DUMP << "\t" << "MathPINumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; break; case V4Instr::LoadNull: INSTR_DUMP << "\t" << "LoadNull" << "\t\t" << "Constant(null) -> Output_Reg(" << i->null_value.reg << ")"; break; - case V4Instr::LoadReal: - INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")"; + case V4Instr::LoadNumber: + INSTR_DUMP << "\t" << "LoadNumber" << "\t\t" << "Constant(" << i->number_value.value << ") -> Output_Reg(" << i->number_value.reg << ")"; break; case V4Instr::LoadInt: INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")"; @@ -249,23 +249,23 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::AddNumber: + INSTR_DUMP << "\t" << "AddNumber" << "\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 << ")"; + case V4Instr::SubNumber: + INSTR_DUMP << "\t" << "SubNumber" << "\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 << ")"; + case V4Instr::MulNumber: + INSTR_DUMP << "\t" << "MulNumber" << "\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 << ")"; + case V4Instr::DivNumber: + INSTR_DUMP << "\t" << "DivNumber" << "\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 << ")"; + case V4Instr::ModNumber: + INSTR_DUMP << "\t" << "ModNumber" << "\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 << ")"; @@ -276,29 +276,29 @@ void Bytecode::dump(const V4Instr *i, int address) const 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 << ")"; + case V4Instr::GtNumber: + INSTR_DUMP << "\t" << "GtNumber" << "\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 << ")"; + case V4Instr::LtNumber: + INSTR_DUMP << "\t" << "LtNumber" << "\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 << ")"; + case V4Instr::GeNumber: + INSTR_DUMP << "\t" << "GeNumber" << "\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 << ")"; + case V4Instr::LeNumber: + INSTR_DUMP << "\t" << "LeNumber" << "\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 << ")"; + case V4Instr::EqualNumber: + INSTR_DUMP << "\t" << "EqualNumber" << "\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 << ")"; + case V4Instr::NotEqualNumber: + INSTR_DUMP << "\t" << "NotEqualNumber" << "\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 << ")"; + case V4Instr::StrictEqualNumber: + INSTR_DUMP << "\t" << "StrictEqualNumber" << "\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 << ")"; + case V4Instr::StrictNotEqualNumber: + INSTR_DUMP << "\t" << "StrictNotEqualNumber" << "\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 << ")"; @@ -336,11 +336,11 @@ void Bytecode::dump(const V4Instr *i, int address) const case V4Instr::StrictNotEqualObject: INSTR_DUMP << "\t" << "StrictNotEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; break; - case V4Instr::MathMaxReal: - INSTR_DUMP << "\t" << "MathMaxReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + case V4Instr::MathMaxNumber: + INSTR_DUMP << "\t" << "MathMaxNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; break; - case V4Instr::MathMinReal: - INSTR_DUMP << "\t" << "MathMinReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + case V4Instr::MathMinNumber: + INSTR_DUMP << "\t" << "MathMinNumber" << "\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 << ")"; @@ -376,12 +376,12 @@ void Bytecode::dump(const V4Instr *i, int address) const 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; + case V4Instr::Throw: + INSTR_DUMP << "\t" << "Throw" << "\t\t\t" << "InputReg(" << i->throwop.message << ")"; + break; default: INSTR_DUMP << "\t" << "Unknown"; break; diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h index 239cb362cc..310bfbaff5 100644 --- a/src/qml/qml/v4/qv4instruction_p.h +++ b/src/qml/qml/v4/qv4instruction_p.h @@ -76,22 +76,22 @@ QT_BEGIN_NAMESPACE F(LoadModuleObject, load) \ F(LoadAttached, attached) \ F(UnaryNot, unaryop) \ - F(UnaryMinusReal, unaryop) \ + F(UnaryMinusNumber, unaryop) \ F(UnaryMinusInt, unaryop) \ - F(UnaryPlusReal, unaryop) \ + F(UnaryPlusNumber, unaryop) \ F(UnaryPlusInt, unaryop) \ F(ConvertBoolToInt, unaryop) \ - F(ConvertBoolToReal, unaryop) \ + F(ConvertBoolToNumber, unaryop) \ F(ConvertBoolToString, unaryop) \ F(ConvertIntToBool, unaryop) \ - F(ConvertIntToReal, unaryop) \ + F(ConvertIntToNumber, unaryop) \ F(ConvertIntToString, unaryop) \ - F(ConvertRealToBool, unaryop) \ - F(ConvertRealToInt, unaryop) \ - F(ConvertRealToString, unaryop) \ + F(ConvertNumberToBool, unaryop) \ + F(ConvertNumberToInt, unaryop) \ + F(ConvertNumberToString, unaryop) \ F(ConvertStringToBool, unaryop) \ F(ConvertStringToInt, unaryop) \ - F(ConvertStringToReal, unaryop) \ + F(ConvertStringToNumber, unaryop) \ F(ConvertStringToUrl, unaryop) \ F(ConvertStringToColor, unaryop) \ F(ConvertUrlToBool, unaryop) \ @@ -101,15 +101,15 @@ QT_BEGIN_NAMESPACE F(ConvertObjectToBool, unaryop) \ F(ConvertNullToObject, unaryop) \ F(ResolveUrl, unaryop) \ - F(MathSinReal, unaryop) \ - F(MathCosReal, unaryop) \ - F(MathAbsReal, unaryop) \ - F(MathRoundReal, unaryop) \ - F(MathFloorReal, unaryop) \ - F(MathCeilReal, unaryop) \ - F(MathPIReal, unaryop) \ + F(MathSinNumber, unaryop) \ + F(MathCosNumber, unaryop) \ + F(MathAbsNumber, unaryop) \ + F(MathRoundNumber, unaryop) \ + F(MathFloorNumber, unaryop) \ + F(MathCeilNumber, unaryop) \ + F(MathPINumber, unaryop) \ F(LoadNull, null_value) \ - F(LoadReal, real_value) \ + F(LoadNumber, number_value) \ F(LoadInt, int_value) \ F(LoadBool, bool_value) \ F(LoadString, string_value) \ @@ -118,23 +118,23 @@ QT_BEGIN_NAMESPACE F(BitAndInt, binaryop) \ F(BitOrInt, binaryop) \ F(BitXorInt, binaryop) \ - F(AddReal, binaryop) \ + F(AddNumber, binaryop) \ F(AddString, binaryop) \ - F(SubReal, binaryop) \ - F(MulReal, binaryop) \ - F(DivReal, binaryop) \ - F(ModReal, binaryop) \ + F(SubNumber, binaryop) \ + F(MulNumber, binaryop) \ + F(DivNumber, binaryop) \ + F(ModNumber, 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(GtNumber, binaryop) \ + F(LtNumber, binaryop) \ + F(GeNumber, binaryop) \ + F(LeNumber, binaryop) \ + F(EqualNumber, binaryop) \ + F(NotEqualNumber, binaryop) \ + F(StrictEqualNumber, binaryop) \ + F(StrictNotEqualNumber, binaryop) \ F(GtString, binaryop) \ F(LtString, binaryop) \ F(GeString, binaryop) \ @@ -147,8 +147,8 @@ QT_BEGIN_NAMESPACE F(NotEqualObject, binaryop) \ F(StrictEqualObject, binaryop) \ F(StrictNotEqualObject, binaryop) \ - F(MathMaxReal, binaryop) \ - F(MathMinReal, binaryop) \ + F(MathMaxNumber, binaryop) \ + F(MathMinNumber, binaryop) \ F(NewString, construct) \ F(NewUrl, construct) \ F(CleanupRegister, cleanup) \ @@ -160,8 +160,7 @@ QT_BEGIN_NAMESPACE F(BranchFalse, branchop) \ F(Branch, branchop) \ F(Block, blockop) \ - /* Speculative property resolution */ \ - F(InitString, initstring) + F(Throw, throwop) #if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) # define QML_THREADED_INTERPRETER @@ -192,7 +191,7 @@ class QQmlNotifier; namespace QQmlJS { -union V4Instr { +union Q_AUTOTEST_EXPORT V4Instr { enum Type { FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM) }; @@ -241,6 +240,7 @@ union V4Instr { qint8 output; qint8 reg; quint8 exceptionId; + quint8 valueType; quint32 index; }; @@ -283,10 +283,10 @@ union V4Instr { qint8 reg; }; - struct instr_real_value { + struct instr_number_value { QML_V4_INSTR_HEADER qint8 reg; - qreal value; // XXX Makes the instruction 12 bytes + double value; // XXX Makes the instruction 12 bytes }; struct instr_int_value { @@ -358,6 +358,12 @@ union V4Instr { quint32 block; }; + struct instr_throwop { + QML_V4_INSTR_HEADER + quint8 exceptionId; + quint32 message; + }; + instr_common common; instr_id id; instr_init init; @@ -371,7 +377,7 @@ union V4Instr { instr_copy copy; instr_construct construct; instr_null_value null_value; - instr_real_value real_value; + instr_number_value number_value; instr_int_value int_value; instr_bool_value bool_value; instr_string_value string_value; @@ -383,6 +389,7 @@ union V4Instr { instr_initstring initstring; instr_branchop branchop; instr_blockop blockop; + instr_throwop throwop; }; template<int N> @@ -400,11 +407,11 @@ 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 Q_AUTOTEST_EXPORT V4InstrData : public V4InstrMeta<Instr>::DataType { }; -class Bytecode +class Q_AUTOTEST_EXPORT Bytecode { Q_DISABLE_COPY(Bytecode) diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp index 34245f5bf4..ba0faec80e 100644 --- a/src/qml/qml/v4/qv4ir.cpp +++ b/src/qml/qml/v4/qv4ir.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { namespace IR { -inline const char *typeName(Type t) +const char *typeName(Type t) { switch (t) { case InvalidType: return "invalid"; @@ -58,15 +58,15 @@ inline const char *typeName(Type t) case NullType: return "null"; case VoidType: return "void"; case StringType: return "string"; - case UrlType: return "url"; - case ColorType: return "color"; + case UrlType: return "QUrl"; + case ColorType: return "QColor"; 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"; + case FloatType: return "float"; + case NumberType: return "number"; default: return "invalid"; } } @@ -91,15 +91,20 @@ IR::Type maxType(IR::Type left, IR::Type right) 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)) || + else if (isNumberType(left) && isNumberType(right)) { + IR::Type ty = qMax(left, right); + return ty == FloatType ? NumberType : ty; // promote floats + } else if ((isNumberType(left) && isStringType(right)) || (isNumberType(right) && isStringType(left))) return IR::StringType; else return IR::InvalidType; } +bool isRealType(IR::Type type) +{ + return type == IR::NumberType || type == IR::FloatType; +} const char *opname(AluOp op) { @@ -233,7 +238,7 @@ void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 builtin = MathMinBuiltinFunction; } else if (id->length() == 7 && *id == QLatin1String("Math.PI")) { builtin = MathPIBuiltinConstant; - this->type = RealType; + this->type = NumberType; } } @@ -267,7 +272,7 @@ Type Unop::typeForOp(AluOp op, Expr *expr) case OpUMinus: case OpUPlus: case OpCompl: - return maxType(expr->type, RealType); + return maxType(expr->type, NumberType); default: break; @@ -309,13 +314,13 @@ Type Binop::typeForOp(AluOp op, Expr *left, Expr *right) case OpAdd: if (left->type == StringType) return StringType; - return RealType; + return NumberType; case OpSub: case OpMul: case OpDiv: case OpMod: - return RealType; + return NumberType; case OpLShift: case OpRShift: @@ -364,7 +369,7 @@ Type Call::typeForFunction(Expr *base) case MathAbsBuiltinFunction: //### type could also be Int if input was Int case MathMaxBuiltinFunction: case MathMinBuiltinFunction: - return RealType; + return NumberType; case MathRoundBultinFunction: case MathFloorBultinFunction: @@ -601,6 +606,12 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) break; } } + } else if (op == OpAdd) { + if (String *s1 = left->asString()) { + if (String *s2 = right->asString()) { + return STRING(function->newString(s1->value.toString() + s2->value)); + } + } } } diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h index 4e9f9faacd..26bd43c406 100644 --- a/src/qml/qml/v4/qv4ir_p.h +++ b/src/qml/qml/v4/qv4ir_p.h @@ -150,10 +150,12 @@ enum Type { FirstNumberType, BoolType = FirstNumberType, IntType, - RealType, - RealNaNType + FloatType, + NumberType }; Type maxType(IR::Type left, IR::Type right); +bool isRealType(IR::Type type); +const char *typeName(IR::Type t); struct ExprVisitor { virtual ~ExprVisitor() {} diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 453120c6c7..31ed9a5a6a 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -61,8 +61,11 @@ static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QM case QMetaType::Int: return IR::IntType; - case QMetaType::QReal: - return IR::RealType; + case QMetaType::Float: + return IR::FloatType; + + case QMetaType::Double: + return IR::NumberType; case QMetaType::QString: return IR::StringType; @@ -542,7 +545,7 @@ bool QV4IRBuilder::visit(AST::NumericLiteral *ast) _expr.format = ExprResult::cx; _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse); } else { - _expr.code = _block->CONST(IR::RealType, ast->value); + _expr.code = _block->CONST(IR::NumberType, ast->value); } return false; } @@ -889,7 +892,14 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult _expr.format = ExprResult::cx; _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); } else { - _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + IR::Expr *e = _block->BINOP(IR::binaryOperator(ast->op), left, right); + if (e->asConst() != 0 || e->asString() != 0) + _expr.code = e; + else { + IR::Temp *t = _block->TEMP(e->type); + _block->MOVE(t, e); + _expr.code = t; + } } } @@ -977,8 +987,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) 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); + implicitCvt(left, IR::NumberType); + implicitCvt(right, IR::NumberType); binop(ast, left, right); } } break; @@ -998,8 +1008,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) } } 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); + implicitCvt(left, IR::NumberType); + implicitCvt(right, IR::NumberType); binop(ast, left, right); } else if (left.isValid() && right.isValid()) { binop(ast, left, right); @@ -1086,8 +1096,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) IR::Type t = maxType(left.type(), right.type()); if (t >= IR::FirstNumberType) { - implicitCvt(left, IR::RealType); - implicitCvt(right, IR::RealType); + implicitCvt(left, IR::NumberType); + implicitCvt(right, IR::NumberType); IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); _expr.code = _block->TEMP(code->type); diff --git a/src/qml/qml/v4/qv4irbuilder_p.h b/src/qml/qml/v4/qv4irbuilder_p.h index 2b338c0778..e73ec22750 100644 --- a/src/qml/qml/v4/qv4irbuilder_p.h +++ b/src/qml/qml/v4/qv4irbuilder_p.h @@ -95,8 +95,8 @@ protected: case QQmlJS::IR::StringType: case QQmlJS::IR::BoolType: case QQmlJS::IR::IntType: - case QQmlJS::IR::RealType: - case QQmlJS::IR::RealNaNType: + case QQmlJS::IR::FloatType: + case QQmlJS::IR::NumberType: return true; default: diff --git a/src/qml/qml/v4/qv4program_p.h b/src/qml/qml/v4/qv4program_p.h index 60e7403786..c1dc39279d 100644 --- a/src/qml/qml/v4/qv4program_p.h +++ b/src/qml/qml/v4/qv4program_p.h @@ -65,7 +65,6 @@ struct QV4Program { quint32 signalTableOffset; quint32 exceptionDataOffset; quint16 subscriptions; - quint16 identifiers; quint16 instructionCount; struct BindingReference { @@ -87,7 +86,8 @@ enum QQmlRegisterType { UndefinedType, NullType, QObjectStarType, - QRealType, + NumberType, + FloatType, IntType, BoolType, |