mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Optimize ECMA double to int32 conversion path (patch by mohammad.r.haghighat@intel.com, r=dvander).
This commit is contained in:
parent
c538fe444e
commit
b43077c19f
@ -965,9 +965,92 @@ js_ValueToECMAInt32(JSContext *cx, jsval *vp)
|
||||
return js_DoubleToECMAInt32(d);
|
||||
}
|
||||
|
||||
/*
|
||||
* From the ES3 spec, 9.5
|
||||
* 2. If Result(1) is NaN, +0, -0, +Inf, or -Inf, return +0.
|
||||
* 3. Compute sign(Result(1)) * floor(abs(Result(1))).
|
||||
* 4. Compute Result(3) modulo 2^32; that is, a finite integer value k of Number
|
||||
* type with positive sign and less than 2^32 in magnitude such the mathematical
|
||||
* difference of Result(3) and k is mathematically an integer multiple of 2^32.
|
||||
* 5. If Result(4) is greater than or equal to 2^31, return Result(4)- 2^32,
|
||||
* otherwise return Result(4).
|
||||
*/
|
||||
int32
|
||||
js_DoubleToECMAInt32(jsdouble d)
|
||||
{
|
||||
#ifdef __i386__
|
||||
jsdpun du, duh, two32;
|
||||
uint32 di_h, u_tmp, expon, shift_amount;
|
||||
int32 mask32;
|
||||
|
||||
/*
|
||||
* Algorithm Outline
|
||||
* Step 1. If d is NaN, +/-Inf or |d|>=2^84 or |d|<1, then return 0
|
||||
* All of this is implemented based on an exponent comparison.
|
||||
* Step 2. If |d|<2^31, then return (int)d
|
||||
* The cast to integer (conversion in RZ mode) returns the correct result.
|
||||
* Step 3. If |d|>=2^32, d:=fmod(d, 2^32) is taken -- but without a call
|
||||
* Step 4. If |d|>=2^31, then the fractional bits are cleared before
|
||||
* applying the correction by 2^32: d - sign(d)*2^32
|
||||
* Step 5. Return (int)d
|
||||
*/
|
||||
|
||||
du.d = d;
|
||||
di_h = du.s.hi;
|
||||
|
||||
u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
|
||||
if (u_tmp >= (0x45300000-0x3ff00000)) {
|
||||
// d is Nan, +/-Inf or +/-0, or |d|>=2^(32+52) or |d|<1, in which case result=0
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (u_tmp < 0x01f00000) {
|
||||
// |d|<2^31
|
||||
return int32_t(d);
|
||||
}
|
||||
|
||||
if (u_tmp > 0x01f00000) {
|
||||
// |d|>=2^32
|
||||
expon = u_tmp >> 20;
|
||||
shift_amount = expon - 21;
|
||||
duh.u64 = du.u64;
|
||||
mask32 = 0x80000000;
|
||||
if (shift_amount < 32) {
|
||||
mask32 >>= shift_amount;
|
||||
duh.s.hi = du.s.hi & mask32;
|
||||
duh.s.lo = 0;
|
||||
} else {
|
||||
mask32 >>= (shift_amount-32);
|
||||
duh.s.hi = du.s.hi;
|
||||
duh.s.lo = du.s.lo & mask32;
|
||||
}
|
||||
du.d -= duh.d;
|
||||
}
|
||||
|
||||
di_h = du.s.hi;
|
||||
|
||||
// eliminate fractional bits
|
||||
u_tmp = (di_h & 0x7ff00000);
|
||||
if (u_tmp >= 0x41e00000) {
|
||||
// |d|>=2^31
|
||||
expon = u_tmp >> 20;
|
||||
shift_amount = expon - (0x3ff - 11);
|
||||
mask32 = 0x80000000;
|
||||
if (shift_amount < 32) {
|
||||
mask32 >>= shift_amount;
|
||||
du.s.hi &= mask32;
|
||||
du.s.lo = 0;
|
||||
} else {
|
||||
mask32 >>= (shift_amount-32);
|
||||
du.s.lo &= mask32;
|
||||
}
|
||||
two32.s.hi = 0x41f00000 ^ (du.s.hi & 0x80000000);
|
||||
two32.s.lo = 0;
|
||||
du.d -= two32.d;
|
||||
}
|
||||
|
||||
return int32(du.d);
|
||||
#else
|
||||
int32 i;
|
||||
jsdouble two32, two31;
|
||||
|
||||
@ -983,6 +1066,7 @@ js_DoubleToECMAInt32(jsdouble d)
|
||||
d = fmod(d, two32);
|
||||
d = (d >= 0) ? floor(d) : ceil(d) + two32;
|
||||
return (int32) (d >= two31 ? d - two32 : d);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32
|
||||
|
Loading…
Reference in New Issue
Block a user