aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v4
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2012-04-11 14:56:22 +0200
committerLars Knoll <lars.knoll@nokia.com>2012-04-11 16:05:03 +0200
commita896d4b39ec3d45ba708d9b36ea9c864b1df2136 (patch)
tree45cfe153cce6114c2c76c48dc0bdabde2a8cf3e3 /src/qml/qml/v4
parent24fb8dc27eddfdd62bd2c3a6e863cbf433762cd6 (diff)
parent65bfc35429e845cf6b76d58107360a1360a654fc (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.cpp456
-rw-r--r--src/qml/qml/v4/qv4bindings_p.h6
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp267
-rw-r--r--src/qml/qml/v4/qv4compiler_p_p.h16
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp130
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h85
-rw-r--r--src/qml/qml/v4/qv4ir.cpp37
-rw-r--r--src/qml/qml/v4/qv4ir_p.h6
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp30
-rw-r--r--src/qml/qml/v4/qv4irbuilder_p.h4
-rw-r--r--src/qml/qml/v4/qv4program_p.h4
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, &notifier);
@@ -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 = &registeredStrings[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,