aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-08-06 22:55:09 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-07 14:20:52 +0200
commitaa6f324c0cea89238c4f557cf00d49ddc8acc4a9 (patch)
tree2ea708acd81f2cb722c0952ce52fdce13f3f9f78 /src
parent36f28fdbebadbd61ff5907b8378abcf907b12dd3 (diff)
Optimize the JS == operator
Implement the isEqualTo vtable method for String, and use that to compare strings and objects in the == implementation in one go. Change-Id: I823ae5c4ed0683105e7a6fc5b414db92d1766fc4 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/v4/qv4runtime.cpp77
-rw-r--r--src/qml/qml/v4/qv4runtime_p.h11
-rw-r--r--src/qml/qml/v4/qv4string.cpp19
-rw-r--r--src/qml/qml/v4/qv4string_p.h2
-rw-r--r--src/qml/qml/v4/qv4value_def_p.h3
-rw-r--r--src/qml/qml/v4/qv4value_p.h2
-rw-r--r--src/qml/qml/v8/qjsvalue.cpp2
7 files changed, 59 insertions, 57 deletions
diff --git a/src/qml/qml/v4/qv4runtime.cpp b/src/qml/qml/v4/qv4runtime.cpp
index 6df48fcea6..ed2c1468ee 100644
--- a/src/qml/qml/v4/qv4runtime.cpp
+++ b/src/qml/qml/v4/qv4runtime.cpp
@@ -685,55 +685,34 @@ void __qmljs_get_activation_property(ExecutionContext *ctx, Value *result, Strin
*result = ctx->getProperty(name);
}
-uint __qmljs_equal(const Value &x, const Value &y)
-{
- if (x.type() == y.type()) {
- switch (x.type()) {
- case Value::Undefined_Type:
- return true;
- case Value::Null_Type:
- return true;
- case Value::Boolean_Type:
- return x.booleanValue() == y.booleanValue();
- break;
- case Value::Integer_Type:
- return x.integerValue() == y.integerValue();
- case Value::String_Type:
- return x.stringValue()->isEqualTo(y.stringValue());
- case Value::Object_Type:
- if (x.objectValue() == y.objectValue())
- return true;
- return x.objectValue()->isEqualTo(y.objectValue());
- default: // double
- return x.doubleValue() == y.doubleValue();
- }
- // unreachable
- } else {
- if (x.isNumber() && y.isNumber())
- return x.asDouble() == y.asDouble();
- if (x.isNull() && y.isUndefined()) {
- return true;
- } else if (x.isUndefined() && y.isNull()) {
- return true;
- } else if (x.isNumber() && y.isString()) {
- Value ny = Value::fromDouble(__qmljs_to_number(y));
- return __qmljs_equal(x, ny);
- } else if (x.isString() && y.isNumber()) {
- Value nx = Value::fromDouble(__qmljs_to_number(x));
- return __qmljs_equal(nx, y);
- } else if (x.isBoolean()) {
- Value nx = Value::fromDouble((double) x.booleanValue());
- return __qmljs_equal(nx, y);
- } else if (y.isBoolean()) {
- Value ny = Value::fromDouble((double) y.booleanValue());
- return __qmljs_equal(x, ny);
- } else if ((x.isNumber() || x.isString()) && y.isObject()) {
- Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT);
- return __qmljs_equal(x, py);
- } else if (x.isObject() && (y.isNumber() || y.isString())) {
- Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT);
- return __qmljs_equal(px, y);
- }
+uint __qmljs_equal_helper(const Value &x, const Value &y)
+{
+ Q_ASSERT(x.type() != y.type());
+
+ if (x.isNumber() && y.isNumber())
+ return x.asDouble() == y.asDouble();
+ if (x.isNull() && y.isUndefined()) {
+ return true;
+ } else if (x.isUndefined() && y.isNull()) {
+ return true;
+ } else if (x.isNumber() && y.isString()) {
+ double dy = __qmljs_to_number(y);
+ return x.asDouble() == dy;
+ } else if (x.isString() && y.isNumber()) {
+ double dx = __qmljs_to_number(x);
+ return dx == y.asDouble();
+ } else if (x.isBoolean()) {
+ Value nx = Value::fromDouble((double) x.booleanValue());
+ return __qmljs_cmp_eq(nx, y);
+ } else if (y.isBoolean()) {
+ Value ny = Value::fromDouble((double) y.booleanValue());
+ return __qmljs_cmp_eq(x, ny);
+ } else if ((x.isNumber() || x.isString()) && y.isObject()) {
+ Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT);
+ return __qmljs_cmp_eq(x, py);
+ } else if (x.isObject() && (y.isNumber() || y.isString())) {
+ Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT);
+ return __qmljs_cmp_eq(px, y);
}
return false;
diff --git a/src/qml/qml/v4/qv4runtime_p.h b/src/qml/qml/v4/qv4runtime_p.h
index 52a8925a47..836aedf298 100644
--- a/src/qml/qml/v4/qv4runtime_p.h
+++ b/src/qml/qml/v4/qv4runtime_p.h
@@ -168,7 +168,7 @@ void __qmljs_numberToString(QString *result, double num, int radix = 10);
QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
-QV4::Bool __qmljs_equal(const QV4::Value &x, const QV4::Value &y);
+QV4::Bool __qmljs_equal_helper(const Value &x, const Value &y);
Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const QV4::Value &x, const QV4::Value &y);
// unary operators
@@ -667,10 +667,13 @@ inline QV4::Bool __qmljs_cmp_eq(const QV4::Value &left, const QV4::Value &right)
// NaN != NaN
return (left.tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
- if (left.isString() && right.isString())
- return left.stringValue()->isEqualTo(right.stringValue());
+ if (left.type() == right.type()) {
+ if (left.isManaged())
+ return left.managed()->isEqualTo(right.managed());
+ return false;
+ }
- return __qmljs_equal(left, right);
+ return __qmljs_equal_helper(left, right);
}
inline QV4::Bool __qmljs_cmp_ne(const QV4::Value &left, const QV4::Value &right)
diff --git a/src/qml/qml/v4/qv4string.cpp b/src/qml/qml/v4/qv4string.cpp
index bfdee2d2cc..8b78c40129 100644
--- a/src/qml/qml/v4/qv4string.cpp
+++ b/src/qml/qml/v4/qv4string.cpp
@@ -119,7 +119,7 @@ const ManagedVTable String::static_vtbl =
deleteIndexedProperty,
0 /*getLookup*/,
0 /*setLookup*/,
- Managed::isEqualTo,
+ isEqualTo,
0 /*advanceIterator*/,
"String",
};
@@ -209,6 +209,23 @@ bool String::deleteIndexedProperty(Managed *m, uint index)
return false;
}
+bool String::isEqualTo(Managed *t, Managed *o)
+{
+ if (t == o)
+ return true;
+ String *that = static_cast<String *>(t);
+ String *other = static_cast<String *>(o);
+ if (that->hashValue() != other->hashValue())
+ return false;
+ if (that->identifier && that->identifier == other->identifier)
+ return true;
+ if (that->subtype >= StringType_UInt && that->subtype == other->subtype)
+ return true;
+
+ return that->toQString() == other->toQString();
+}
+
+
String::String(ExecutionEngine *engine, const QString &text)
: Managed(engine ? engine->emptyClass : 0), _text(text), identifier(0), stringHash(UINT_MAX)
{
diff --git a/src/qml/qml/v4/qv4string_p.h b/src/qml/qml/v4/qv4string_p.h
index 629fa506b7..31e5c2a5f7 100644
--- a/src/qml/qml/v4/qv4string_p.h
+++ b/src/qml/qml/v4/qv4string_p.h
@@ -123,6 +123,7 @@ struct Q_QML_EXPORT String : public Managed {
mutable Identifier *identifier;
mutable uint stringHash;
+
protected:
static void destroy(Managed *);
static Value get(Managed *m, String *name, bool *hasProperty);
@@ -133,6 +134,7 @@ protected:
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *, String *);
static bool deleteIndexedProperty(Managed *m, uint index);
+ static bool isEqualTo(Managed *that, Managed *o);
static const ManagedVTable static_vtbl;
};
diff --git a/src/qml/qml/v4/qv4value_def_p.h b/src/qml/qml/v4/qv4value_def_p.h
index 89f6647e22..a44af16b6a 100644
--- a/src/qml/qml/v4/qv4value_def_p.h
+++ b/src/qml/qml/v4/qv4value_def_p.h
@@ -79,7 +79,7 @@ struct Q_QML_EXPORT Value
NotDouble_Mask = 0x7ffc0000,
Type_Mask = 0xffff8000,
Immediate_Mask = NotDouble_Mask | 0x00008000,
- Special_Mask = Immediate_Mask | 0x20000,
+ IsManaged_Mask = Type_Mask & ~0x10000,
Tag_Shift = 32
};
enum ValueType {
@@ -127,6 +127,7 @@ struct Q_QML_EXPORT Value
inline bool isString() const { return tag == String_Type; }
inline bool isObject() const { return tag == Object_Type; }
#endif
+ inline bool isManaged() const { return (tag & IsManaged_Mask) == Object_Type; }
inline bool isConvertibleToInt() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
inline bool isInt32() {
if (tag == _Integer_Type)
diff --git a/src/qml/qml/v4/qv4value_p.h b/src/qml/qml/v4/qv4value_p.h
index 6d3f0e6edc..2a783ed34b 100644
--- a/src/qml/qml/v4/qv4value_p.h
+++ b/src/qml/qml/v4/qv4value_p.h
@@ -276,7 +276,7 @@ inline String *Value::asString() const
inline Managed *Value::asManaged() const
{
- if (isObject() || isString())
+ if (isManaged())
return managed();
return 0;
}
diff --git a/src/qml/qml/v8/qjsvalue.cpp b/src/qml/qml/v8/qjsvalue.cpp
index 2fab183bd0..569dd964fd 100644
--- a/src/qml/qml/v8/qjsvalue.cpp
+++ b/src/qml/qml/v8/qjsvalue.cpp
@@ -747,7 +747,7 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
*/
bool QJSValue::equals(const QJSValue& other) const
{
- return __qmljs_equal(d->value, other.d->value);
+ return __qmljs_cmp_eq(d->value, other.d->value);
}
/*!