diff options
author | Lars Knoll <[email protected]> | 2013-08-06 22:55:09 +0200 |
---|---|---|
committer | The Qt Project <[email protected]> | 2013-08-07 14:20:52 +0200 |
commit | aa6f324c0cea89238c4f557cf00d49ddc8acc4a9 (patch) | |
tree | 2ea708acd81f2cb722c0952ce52fdce13f3f9f78 /src | |
parent | 36f28fdbebadbd61ff5907b8378abcf907b12dd3 (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 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/v4/qv4runtime.cpp | 77 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4runtime_p.h | 11 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4string.cpp | 19 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4string_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4value_def_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4value_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/v8/qjsvalue.cpp | 2 |
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); } /*! |