From 86a31a3dff5fc6848f9a9a7b5798fb87e86b1fe1 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 18 Oct 2012 12:04:51 +0200 Subject: [PATCH] Fix integer arithmetics The inline assembly could create incorrect results for overflows, esp when multiplying. Also fix the return type of Value::integerValue() Change-Id: I4c8f195b37bcbb8fd4f0f3d0cd04a8cf73f193cd Reviewed-by: Simon Hausmann --- qmljs_math.h | 27 +++++++++++++++------------ qmljs_runtime.h | 11 ++++++----- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/qmljs_math.h b/qmljs_math.h index 588efb1138..7823eeccc7 100644 --- a/qmljs_math.h +++ b/qmljs_math.h @@ -51,45 +51,48 @@ static inline Value add_int32(int a, int b) { quint8 overflow = 0; + int aa = a; asm ("addl %2, %1\n" "seto %0" - : "=q" (overflow), "=r" (a) - : "r" (b), "1" (a) + : "=q" (overflow), "=r" (aa) + : "r" (b), "1" (aa) : ); if (!overflow) - return Value::fromInt32(a); + return Value::fromInt32(aa); return Value::fromDouble((double)a + (double)b); } static inline Value sub_int32(int a, int b) { quint8 overflow = 0; + int aa = a; asm ("subl %2, %1\n" "seto %0" - : "=q" (overflow), "=r" (a) - : "r" (b), "1" (a) + : "=q" (overflow), "=r" (aa) + : "r" (b), "1" (aa) : ); if (!overflow) - return Value::fromInt32(a); + return Value::fromInt32(aa); return Value::fromDouble((double)a - (double)b); } static inline Value mul_int32(int a, int b) { quint8 overflow = 0; + int aa = a; - asm ("imul %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (a) - : "r" (b), "1" (a) - : + asm ("imul %2\n" + "setc %0" + : "=q" (overflow), "=a" (aa) + : "r" (b), "1" (aa) + : "edx" ); if (!overflow) - return Value::fromInt32(a); + return Value::fromInt32(aa); return Value::fromDouble((double)a * (double)b); } #endif diff --git a/qmljs_runtime.h b/qmljs_runtime.h index fc9d49ae77..6907eb4708 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -162,7 +162,6 @@ Value __qmljs_to_object(Value value, Context *ctx); Bool __qmljs_is_callable(Value value, Context *ctx); Value __qmljs_default_value(Value value, Context *ctx, int typeHint); -Value __qmljs_compare(Value left, Value right, Context *ctx, bool leftFlag); Bool __qmljs_equal(Value x, Value y, Context *ctx); Bool __qmljs_strict_equal(Value x, Value y, Context *ctx); @@ -334,7 +333,7 @@ template <> struct ValueBase<4> : public ValueData return int_32; return dbl; } - double integerValue() const { + int integerValue() const { return int_32; } @@ -400,7 +399,7 @@ template <> struct ValueBase<8> : public ValueData return int_32; return dbl; } - double integerValue() const { + int integerValue() const { return int_32; } @@ -939,8 +938,7 @@ inline Value __qmljs_bit_or(Value left, Value right, Context *ctx) { int lval = __qmljs_to_int32(left, ctx); int rval = __qmljs_to_int32(right, ctx); - // ### changing this to fromInt32() breaks crypto.js - return Value::fromDouble(lval | rval); + return Value::fromInt32(lval | rval); } inline Value __qmljs_bit_xor(Value left, Value right, Context *ctx) @@ -1054,6 +1052,9 @@ inline Value __qmljs_div(Value left, Value right, Context *ctx) inline Value __qmljs_mod(Value left, Value right, Context *ctx) { + if (left.isInteger() && right.isInteger()) + return Value::fromInt32(left.integerValue() % right.integerValue()); + double lval = __qmljs_to_number(left, ctx); double rval = __qmljs_to_number(right, ctx); return Value::fromDouble(fmod(lval, rval));