fix: jv_number_value should cache the double value of literal numbers (#3245)

The code of `jv_number_value` is intended to cache the double value of
literal numbers, but it does not work because it accepts the `jv` struct
by value. This patch fixes the behavior by checking if the double value
is `NaN`, which indicates the unconverted value. This patch improves the
performance of major use cases; e.g. `range(1000000)` runs 25% faster.
This commit is contained in:
itchyny authored and GitHub committed 2025-02-16 22:08:36 +09:00
1 parent 64bd8ba374
commit b86ff49f46
1 file changed
+7 -7
+7 -7
View File
@@ -206,9 +206,6 @@ enum {
JVP_NUMBER_DECIMAL = 1
};
#define JV_NUMBER_SIZE_INIT (0)
#define JV_NUMBER_SIZE_CONVERTED (1)
#define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0))
#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
@@ -587,8 +584,12 @@ static jv jvp_literal_number_new(const char * literal) {
jv_mem_free(n);
return JV_INVALID;
}
if (decNumberIsNaN(&n->num_decimal)) {
jv_mem_free(n);
return jv_number(NAN);
}
jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}};
jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&n->refcnt}};
return r;
}
@@ -696,9 +697,8 @@ double jv_number_value(jv j) {
if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) {
jvp_literal_number* n = jvp_literal_number_ptr(j);
if (j.size != JV_NUMBER_SIZE_CONVERTED) {
if (isnan(n->num_double)) {
n->num_double = jvp_literal_number_to_double(j);
j.size = JV_NUMBER_SIZE_CONVERTED;
}
return n->num_double;
@@ -729,7 +729,7 @@ int jvp_number_is_nan(jv n) {
return decNumberIsNaN(pdec);
}
#endif
return n.u.number != n.u.number;
return isnan(n.u.number);
}
jv jv_number_negate(jv n) {