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 <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2012-10-18 12:04:51 +02:00 committed by Simon Hausmann
parent 19af71d4bf
commit 86a31a3dff
2 changed files with 21 additions and 17 deletions

View File

@ -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

View File

@ -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));