Optimize some runtime methods
authorLars Knoll <lars.knoll@digia.com>
Sat, 14 Sep 2013 13:08:11 +0000 (15:08 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 18 Sep 2013 11:14:16 +0000 (13:14 +0200)
This prings performance up by ~25% again.

Change-Id: I680466e11b722b2eac0edda0fe4199b717d23855
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/jsruntime/qv4runtime_p.h
src/qml/jsruntime/qv4value.cpp
src/qml/jsruntime/qv4value_def_p.h
src/qml/jsruntime/qv4value_p.h

index 03d00fc..4e865ef 100644 (file)
@@ -298,12 +298,11 @@ inline QV4::ReturnedValue __qmljs_uplus(const QV4::ValueRef value)
 {
     TRACE1(value);
 
-    Value result = *value;
-    if (result.tryIntegerConversion())
-        return result.asReturnedValue();
+    if (value->isConvertibleToInt())
+        return Encode(value->int_32);
 
-    double n = __qmljs_to_number(value);
-    return QV4::Value::fromDouble(n).asReturnedValue();
+    double n = value->toNumber();
+    return Encode(n);
 }
 
 inline QV4::ReturnedValue __qmljs_uminus(const QV4::ValueRef value)
@@ -327,9 +326,9 @@ inline QV4::ReturnedValue __qmljs_compl(const QV4::ValueRef value)
     if (value->isConvertibleToInt())
         n = value->int_32;
     else
-        n = QV4::Value::toInt32(__qmljs_to_number(value));
+        n = value->toInt32();
 
-    return QV4::Value::fromInt32(~n).asReturnedValue();
+    return Encode((int)~n);
 }
 
 inline QV4::ReturnedValue __qmljs_not(const QV4::ValueRef value)
@@ -337,7 +336,7 @@ inline QV4::ReturnedValue __qmljs_not(const QV4::ValueRef value)
     TRACE1(value);
 
     bool b = value->toBoolean();
-    return QV4::Value::fromBoolean(!b).asReturnedValue();
+    return Encode(!b);
 }
 
 // binary operators
@@ -348,8 +347,8 @@ inline ReturnedValue __qmljs_bit_or(const QV4::ValueRef left, const QV4::ValueRe
     if (QV4::Value::integerCompatible(*left, *right))
         return QV4::Value::fromInt32(left->integerValue() | right->integerValue()).asReturnedValue();
 
-    int lval = QV4::Value::toInt32(__qmljs_to_number(left));
-    int rval = QV4::Value::toInt32(__qmljs_to_number(right));
+    int lval = left->toInt32();
+    int rval = right->toInt32();
     return QV4::Value::fromInt32(lval | rval).asReturnedValue();
 }
 
@@ -360,8 +359,8 @@ inline ReturnedValue __qmljs_bit_xor(const QV4::ValueRef left, const QV4::ValueR
     if (QV4::Value::integerCompatible(*left, *right))
         return QV4::Value::fromInt32(left->integerValue() ^ right->integerValue()).asReturnedValue();
 
-    int lval = QV4::Value::toInt32(__qmljs_to_number(left));
-    int rval = QV4::Value::toInt32(__qmljs_to_number(right));
+    int lval = left->toInt32();
+    int rval = right->toInt32();
     return QV4::Value::fromInt32(lval ^ rval).asReturnedValue();
 }
 
@@ -372,8 +371,8 @@ inline ReturnedValue __qmljs_bit_and(const QV4::ValueRef left, const QV4::ValueR
     if (QV4::Value::integerCompatible(*left, *right))
         return QV4::Value::fromInt32(left->integerValue() & right->integerValue()).asReturnedValue();
 
-    int lval = QV4::Value::toInt32(__qmljs_to_number(left));
-    int rval = QV4::Value::toInt32(__qmljs_to_number(right));
+    int lval = left->toInt32();
+    int rval = right->toInt32();
     return QV4::Value::fromInt32(lval & rval).asReturnedValue();
 }
 
@@ -445,8 +444,8 @@ inline QV4::ReturnedValue __qmljs_shl(const QV4::ValueRef left, const QV4::Value
     if (QV4::Value::integerCompatible(*left, *right))
         return QV4::Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f))).asReturnedValue();
 
-    int lval = QV4::Value::toInt32(__qmljs_to_number(left));
-    unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
+    int lval = left->toInt32();
+    unsigned rval = right->toUInt32() & 0x1f;
     return QV4::Value::fromInt32(lval << rval).asReturnedValue();
 }
 
@@ -457,8 +456,8 @@ inline QV4::ReturnedValue __qmljs_shr(const QV4::ValueRef left, const QV4::Value
     if (QV4::Value::integerCompatible(*left, *right))
         return QV4::Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f))).asReturnedValue();
 
-    int lval = QV4::Value::toInt32(__qmljs_to_number(left));
-    unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
+    int lval = left->toInt32();
+    unsigned rval = right->toUInt32() & 0x1f;
     return QV4::Value::fromInt32(lval >> rval).asReturnedValue();
 }
 
@@ -470,8 +469,8 @@ inline QV4::ReturnedValue __qmljs_ushr(const QV4::ValueRef left, const QV4::Valu
     if (QV4::Value::integerCompatible(*left, *right)) {
         res = uint(left->integerValue()) >> (uint(right->integerValue()) & 0x1f);
     } else {
-        unsigned lval = QV4::Value::toUInt32(__qmljs_to_number(left));
-        unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
+        unsigned lval = left->toUInt32();
+        unsigned rval = right->toUInt32() & 0x1f;
         res = lval >> rval;
     }
 
index 79bfae4..aa96268 100644 (file)
 
 using namespace QV4;
 
-int Value::toInt32() const
-{
-    if (isConvertibleToInt())
-        return int_32;
-    double d;
-    if (isDouble())
-        d = dbl;
-    else
-        d = toNumber();
-
-    const double D32 = 4294967296.0;
-    const double D31 = D32 / 2.0;
-
-    if ((d >= -D31 && d < D31))
-        return static_cast<int>(d);
-
-    return Value::toInt32(d);
-}
-
-unsigned int Value::toUInt32() const
-{
-    if (isConvertibleToInt())
-        return (unsigned) int_32;
-    double d;
-    if (isDouble())
-        d = dbl;
-    else
-        d = toNumber();
-
-    const double D32 = 4294967296.0;
-    if (d >= 0 && d < D32)
-        return static_cast<uint>(d);
-    return toUInt32(d);
-}
-
 int Value::toUInt16() const
 {
     if (isConvertibleToInt())
@@ -117,17 +82,11 @@ double Value::toInteger() const
     return Value::toInteger(toNumber());
 }
 
-double Value::toNumber() const
+double Value::toNumberImpl() const
 {
     switch (type()) {
     case QV4::Value::Undefined_Type:
         return std::numeric_limits<double>::quiet_NaN();
-    case QV4::Value::Null_Type:
-        return 0;
-    case QV4::Value::Boolean_Type:
-        return (booleanValue() ? 1. : 0.);
-    case QV4::Value::Integer_Type:
-        return int_32;
     case QV4::Value::String_Type:
         return __qmljs_string_to_number(stringValue()->toQString());
     case QV4::Value::Object_Type: {
@@ -136,8 +95,11 @@ double Value::toNumber() const
         ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), NUMBER_HINT));
         return prim->toNumber();
     }
+    case QV4::Value::Null_Type:
+    case QV4::Value::Boolean_Type:
+    case QV4::Value::Integer_Type:
     default: // double
-        return doubleValue();
+        Q_UNREACHABLE();
     }
 }
 
index 866e5e7..d83a4c4 100644 (file)
@@ -215,6 +215,7 @@ struct Q_QML_EXPORT Value
     bool toBoolean() const;
     double toInteger() const;
     double toNumber() const;
+    double toNumberImpl() const;
     QString toQStringNoThrow() const;
     QString toQString() const;
     String *toString(ExecutionContext *ctx) const;
index 8f980e0..cfe03be 100644 (file)
@@ -171,6 +171,51 @@ inline Value Value::fromObject(Object *o)
     return v;
 }
 
+inline double Value::toNumber() const
+{
+    if (isConvertibleToInt())
+        return int_32;
+    if (isDouble())
+        return dbl;
+    return toNumberImpl();
+}
+
+inline int Value::toInt32() const
+{
+    if (isConvertibleToInt())
+        return int_32;
+    double d;
+    if (isDouble())
+        d = dbl;
+    else
+        d = toNumberImpl();
+
+    const double D32 = 4294967296.0;
+    const double D31 = D32 / 2.0;
+
+    if ((d >= -D31 && d < D31))
+        return static_cast<int>(d);
+
+    return Value::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
+{
+    if (isConvertibleToInt())
+        return (unsigned) int_32;
+    double d;
+    if (isDouble())
+        d = dbl;
+    else
+        d = toNumberImpl();
+
+    const double D32 = 4294967296.0;
+    if (d >= 0 && d < D32)
+        return static_cast<uint>(d);
+    return toUInt32(d);
+}
+
+
 inline bool Value::toBoolean() const
 {
     switch (type()) {