fix number rep
This commit is contained in:
@@ -166,7 +166,7 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
case JS_TAG_NULL:
|
||||
nota_write_sym(&enc->nb, NOTA_NULL);
|
||||
break;
|
||||
case JS_TAG_OBJECT: {
|
||||
case JS_TAG_PTR: {
|
||||
if (js_is_blob(ctx, replaced)) {
|
||||
size_t buf_len;
|
||||
void *buf_data = js_get_blob_data(ctx, &buf_len, replaced);
|
||||
|
||||
@@ -156,7 +156,7 @@ static void wota_encode_value(WotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
case JS_TAG_NULL:
|
||||
wota_write_sym(&enc->wb, WOTA_NULL);
|
||||
break;
|
||||
case JS_TAG_OBJECT: {
|
||||
case JS_TAG_PTR: {
|
||||
if (js_is_blob(ctx, replaced)) {
|
||||
size_t buf_len;
|
||||
void *buf_data = js_get_blob_data(ctx, &buf_len, replaced);
|
||||
|
||||
@@ -5205,7 +5205,7 @@ static int JS_ToBoolFree (JSContext *ctx, JSValue val) {
|
||||
default:
|
||||
if (JS_TAG_IS_FLOAT64 (tag)) {
|
||||
double d = JS_VALUE_GET_FLOAT64 (val);
|
||||
return !isnan (d) && d != 0;
|
||||
return d != 0; /* NaN impossible in short floats */
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
@@ -5521,16 +5521,13 @@ redo:
|
||||
return -1;
|
||||
case JS_TAG_FLOAT64: {
|
||||
double d = JS_VALUE_GET_FLOAT64 (val);
|
||||
if (isnan (d)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (d < INT32_MIN)
|
||||
ret = INT32_MIN;
|
||||
else if (d > INT32_MAX)
|
||||
ret = INT32_MAX;
|
||||
else
|
||||
ret = (int)d;
|
||||
}
|
||||
/* NaN impossible in short floats */
|
||||
if (d < INT32_MIN)
|
||||
ret = INT32_MIN;
|
||||
else if (d > INT32_MAX)
|
||||
ret = INT32_MAX;
|
||||
else
|
||||
ret = (int)d;
|
||||
} break;
|
||||
default:
|
||||
val = JS_ToNumberFree (ctx, val);
|
||||
@@ -5577,17 +5574,14 @@ redo:
|
||||
return -1;
|
||||
case JS_TAG_FLOAT64: {
|
||||
double d = JS_VALUE_GET_FLOAT64 (val);
|
||||
if (isnan (d)) {
|
||||
*pres = 0;
|
||||
} else {
|
||||
if (d < INT64_MIN)
|
||||
*pres = INT64_MIN;
|
||||
else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot
|
||||
be exactly represented as a double */
|
||||
*pres = INT64_MAX;
|
||||
else
|
||||
*pres = (int64_t)d;
|
||||
}
|
||||
/* NaN impossible in short floats */
|
||||
if (d < INT64_MIN)
|
||||
*pres = INT64_MIN;
|
||||
else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot
|
||||
be exactly represented as a double */
|
||||
*pres = INT64_MAX;
|
||||
else
|
||||
*pres = (int64_t)d;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
@@ -6409,12 +6403,7 @@ js_unary_arith_slow (JSContext *ctx, JSValue *sp, OPCodeEnum op) {
|
||||
case OP_plus:
|
||||
break;
|
||||
case OP_neg:
|
||||
if (v64 == 0) {
|
||||
sp[-1] = __JS_NewFloat64 (ctx, -0.0);
|
||||
return 0;
|
||||
} else {
|
||||
v64 = -v64;
|
||||
}
|
||||
v64 = -v64; /* -0 normalized to 0 by __JS_NewFloat64 */
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
@@ -6518,10 +6507,7 @@ js_binary_arith_slow (JSContext *ctx, JSValue *sp, OPCodeEnum op) {
|
||||
break;
|
||||
case OP_mul:
|
||||
v = (int64_t)v1 * (int64_t)v2;
|
||||
if (v == 0 && (v1 | v2) < 0) {
|
||||
sp[-2] = __JS_NewFloat64 (ctx, -0.0);
|
||||
return 0;
|
||||
}
|
||||
/* -0 normalized to 0, no special case needed */
|
||||
break;
|
||||
case OP_div:
|
||||
sp[-2] = JS_NewFloat64 (ctx, (double)v1 / (double)v2);
|
||||
@@ -8548,11 +8534,7 @@ restart:
|
||||
d = (double)r;
|
||||
goto mul_fp_res;
|
||||
}
|
||||
/* need to test zero case for -0 result */
|
||||
if (unlikely (r == 0 && (v1 | v2) < 0)) {
|
||||
d = -0.0;
|
||||
goto mul_fp_res;
|
||||
}
|
||||
/* -0 normalized to 0, no special case needed */
|
||||
sp[-2] = JS_NewInt32 (ctx, r);
|
||||
sp--;
|
||||
} else if (JS_VALUE_IS_BOTH_FLOAT (op1, op2)) {
|
||||
@@ -8625,11 +8607,7 @@ restart:
|
||||
tag = JS_VALUE_GET_TAG (op1);
|
||||
if (tag == JS_TAG_INT) {
|
||||
val = JS_VALUE_GET_INT (op1);
|
||||
/* Note: -0 cannot be expressed as integer */
|
||||
if (unlikely (val == 0)) {
|
||||
d = -0.0;
|
||||
goto neg_fp_res;
|
||||
}
|
||||
/* -0 normalized to 0, val==0 just stays 0 */
|
||||
if (unlikely (val == INT32_MIN)) {
|
||||
d = -(double)val;
|
||||
goto neg_fp_res;
|
||||
|
||||
@@ -240,8 +240,8 @@ __JS_NewFloat64 (JSContext *ctx, double d) {
|
||||
int exp = (u.u >> 52) & 0x7FF;
|
||||
uint64_t mantissa = u.u & ((1ULL << 52) - 1);
|
||||
|
||||
/* Zero → short float zero */
|
||||
if (exp == 0 && mantissa == 0) { return (sign << 63) | JS_TAG_SHORT_FLOAT; }
|
||||
/* Zero → short float zero (always +0, no -0) */
|
||||
if (exp == 0 && mantissa == 0) { return JS_TAG_SHORT_FLOAT; }
|
||||
|
||||
/* NaN/Inf → NULL */
|
||||
if (exp == 0x7FF) { return JS_MKVAL (JS_TAG_NULL, 0); }
|
||||
@@ -273,7 +273,7 @@ static inline double JS_VALUE_GET_FLOAT64 (JSValue v) {
|
||||
uint64_t short_exp = (v >> 55) & 0xFF;
|
||||
uint64_t mantissa = (v >> 3) & ((1ULL << 52) - 1);
|
||||
|
||||
if (short_exp == 0) return sign ? -0.0 : 0.0;
|
||||
if (short_exp == 0) return 0.0; /* Always +0, no -0 */
|
||||
|
||||
uint64_t exp = short_exp - 127 + 1023;
|
||||
union {
|
||||
|
||||
@@ -1244,15 +1244,16 @@ return {
|
||||
// EDGE CASES AND SPECIAL VALUES
|
||||
// ============================================================================
|
||||
|
||||
test_infinity: function() {
|
||||
test_division_by_zero_is_null: function() {
|
||||
var inf = 1 / 0
|
||||
if (!(inf > 1000000)) throw "infinity failed"
|
||||
if (!(-inf < -1000000)) throw "negative infinity failed"
|
||||
if (inf != null) throw "division by zero should be null"
|
||||
var ninf = -1 / 0
|
||||
if (ninf != null) throw "negative division by zero should be null"
|
||||
},
|
||||
|
||||
test_nan: function() {
|
||||
test_zero_div_zero_is_null: function() {
|
||||
var nan = 0 / 0
|
||||
if (nan == nan) throw "NaN should not equal itself"
|
||||
if (nan != null) throw "0/0 should be null"
|
||||
},
|
||||
|
||||
test_max_safe_integer: function() {
|
||||
@@ -1403,17 +1404,36 @@ return {
|
||||
|
||||
test_number_division_by_zero: function() {
|
||||
var result = 1 / 0
|
||||
if (!(result > 1000000)) throw "division by zero should give infinity"
|
||||
if (result != null) throw "division by zero should give null"
|
||||
},
|
||||
|
||||
test_number_negative_division_by_zero: function() {
|
||||
var result = -1 / 0
|
||||
if (!(result < -1000000)) throw "negative division by zero should give -infinity"
|
||||
if (result != null) throw "negative division by zero should give null"
|
||||
},
|
||||
|
||||
test_zero_division_by_zero: function() {
|
||||
var result = 0 / 0
|
||||
if (result == result) throw "0/0 should give NaN"
|
||||
if (result != null) throw "0/0 should give null"
|
||||
},
|
||||
|
||||
test_negative_zero_normalized: function() {
|
||||
var nz = -0
|
||||
if (nz != 0) throw "-0 should equal 0"
|
||||
var mul_nz = 0 * -1
|
||||
if (mul_nz != 0) throw "0 * -1 should be 0"
|
||||
var neg_zero = -(0)
|
||||
if (neg_zero != 0) throw "-(0) should be 0"
|
||||
},
|
||||
|
||||
test_overflow_is_null: function() {
|
||||
var result = 1e38 * 1e38
|
||||
if (result != null) throw "overflow should give null"
|
||||
},
|
||||
|
||||
test_modulo_by_zero_is_null: function() {
|
||||
var result = 5 % 0
|
||||
if (result != null) throw "modulo by zero should give null"
|
||||
},
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user