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:
parent
19af71d4bf
commit
86a31a3dff
27
qmljs_math.h
27
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
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue