V4 runtime: tune Runtime::add/sub/mul a bit.
authorErik Verbruggen <erik.verbruggen@digia.com>
Fri, 22 Aug 2014 10:29:20 +0000 (12:29 +0200)
committerErik Verbruggen <erik.verbruggen@digia.com>
Wed, 10 Sep 2014 13:52:24 +0000 (15:52 +0200)
Tell the compiler to schedule the int32 case first, tune the double
conversion a bit (int64->double is quite expensive), and write the
function in such a way that it matches typical overflow idiom which
compilers recognize.

Change-Id: Ieae9a60275716002fbdbc54e1d7291c8aad8c927
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/jsruntime/qv4math_p.h
src/qml/jsruntime/qv4runtime_p.h

index 7f194bd..4fdad40 100644 (file)
@@ -35,9 +35,7 @@
 
 #include <qglobal.h>
 
-#ifndef QMLJS_LLVM_RUNTIME
-#  include <QtCore/qnumeric.h>
-#endif // QMLJS_LLVM_RUNTIME
+#include <QtCore/qnumeric.h>
 #include <cmath>
 
 #if defined(Q_CC_GNU)
@@ -50,9 +48,9 @@ QT_BEGIN_NAMESPACE
 
 namespace QV4 {
 
-#if !defined(QMLJS_LLVM_RUNTIME) && defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
+#if defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
 
-static inline QMLJS_READONLY Value add_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b)
 {
     quint8 overflow = 0;
     int aa = a;
@@ -63,13 +61,12 @@ static inline QMLJS_READONLY Value add_int32(int a, int b)
          : "r" (b), "1" (aa)
          : "cc"
     );
-    if (!overflow)
-        return Primitive::fromInt32(aa);
-    qint64 result = static_cast<qint64>(a) + b;
-    return Primitive::fromDouble(result);
+    if (Q_UNLIKELY(overflow))
+        return Primitive::fromDouble(static_cast<double>(a) + b).asReturnedValue();
+    return Primitive::fromInt32(aa).asReturnedValue();
 }
 
-static inline QMLJS_READONLY Value sub_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
 {
     quint8 overflow = 0;
     int aa = a;
@@ -80,13 +77,12 @@ static inline QMLJS_READONLY Value sub_int32(int a, int b)
          : "r" (b), "1" (aa)
          : "cc"
     );
-    if (!overflow)
-        return Primitive::fromInt32(aa);
-    qint64 result = static_cast<qint64>(a) - b;
-    return Primitive::fromDouble(result);
+    if (Q_UNLIKELY(overflow))
+        return Primitive::fromDouble(static_cast<double>(a) - b).asReturnedValue();
+    return Primitive::fromInt32(aa).asReturnedValue();
 }
 
-static inline QMLJS_READONLY Value mul_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
 {
     quint8 overflow = 0;
     int aa = a;
@@ -97,39 +93,38 @@ static inline QMLJS_READONLY Value mul_int32(int a, int b)
          : "r" (b), "1" (aa)
          : "cc"
     );
-    if (!overflow)
-        return Primitive::fromInt32(aa);
-    qint64 result = static_cast<qint64>(a) * b;
-    return Primitive::fromDouble(result);
+    if (Q_UNLIKELY(overflow))
+        return Primitive::fromDouble(static_cast<double>(a) * b).asReturnedValue();
+    return Primitive::fromInt32(aa).asReturnedValue();
 }
 
 #else
 
-static inline QMLJS_READONLY Value add_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b)
 {
     qint64 result = static_cast<qint64>(a) + b;
-    if (result > INT_MAX || result < INT_MIN)
-        return Primitive::fromDouble(result);
-    return Primitive::fromInt32(static_cast<int>(result));
+    if (Q_UNLIKELY(result > INT_MAX || result < INT_MIN))
+        return Primitive::fromDouble(static_cast<double>(a) + b).asReturnedValue();
+    return Primitive::fromInt32(static_cast<int>(result)).asReturnedValue();
 }
 
-static inline QMLJS_READONLY Value sub_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
 {
     qint64 result = static_cast<qint64>(a) - b;
-    if (result > INT_MAX || result < INT_MIN)
-        return Primitive::fromDouble(result);
-    return Primitive::fromInt32(static_cast<int>(result));
+    if (Q_UNLIKELY(result > INT_MAX || result < INT_MIN))
+        return Primitive::fromDouble(static_cast<double>(a) - b).asReturnedValue();
+    return Primitive::fromInt32(static_cast<int>(result)).asReturnedValue();
 }
 
-static inline QMLJS_READONLY Value mul_int32(int a, int b)
+static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
 {
     qint64 result = static_cast<qint64>(a) * b;
-    if (result > INT_MAX || result < INT_MIN)
-        return Primitive::fromDouble(result);
-    return Primitive::fromInt32(static_cast<int>(result));
+    if (Q_UNLIKELY(result > INT_MAX || result < INT_MIN))
+        return Primitive::fromDouble(static_cast<double>(a) * b).asReturnedValue();
+    return Primitive::fromInt32(static_cast<int>(result)).asReturnedValue();
 }
 
-#endif // defined(QMLJS_INLINE_MATH)
+#endif
 
 }
 
index 53aea52..6042420 100644 (file)
@@ -338,8 +338,8 @@ inline ReturnedValue Runtime::add(ExecutionContext *ctx, const ValueRef left, co
 {
     TRACE2(left, right);
 
-    if (left->isInteger() && right->isInteger())
-        return add_int32(left->integerValue(), right->integerValue()).asReturnedValue();
+    if (Q_LIKELY(left->isInteger() && right->isInteger()))
+        return add_int32(left->integerValue(), right->integerValue());
     if (left->isNumber() && right->isNumber())
         return Primitive::fromDouble(left->asDouble() + right->asDouble()).asReturnedValue();
 
@@ -351,8 +351,8 @@ inline ReturnedValue Runtime::sub(const ValueRef left, const ValueRef right)
 {
     TRACE2(left, right);
 
-    if (left->isInteger() && right->isInteger())
-        return sub_int32(left->integerValue(), right->integerValue()).asReturnedValue();
+    if (Q_LIKELY(left->isInteger() && right->isInteger()))
+        return sub_int32(left->integerValue(), right->integerValue());
 
     double lval = left->isNumber() ? left->asDouble() : left->toNumberImpl();
     double rval = right->isNumber() ? right->asDouble() : right->toNumberImpl();
@@ -364,8 +364,8 @@ inline ReturnedValue Runtime::mul(const ValueRef left, const ValueRef right)
 {
     TRACE2(left, right);
 
-    if (left->isInteger() && right->isInteger())
-        return mul_int32(left->integerValue(), right->integerValue()).asReturnedValue();
+    if (Q_LIKELY(left->isInteger() && right->isInteger()))
+        return mul_int32(left->integerValue(), right->integerValue());
 
     double lval = left->isNumber() ? left->asDouble() : left->toNumberImpl();
     double rval = right->isNumber() ? right->asDouble() : right->toNumberImpl();