diff options
Diffstat (limited to 'src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c')
-rw-r--r-- | src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c b/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c new file mode 100644 index 000000000..a1d0f88f1 --- /dev/null +++ b/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c @@ -0,0 +1,138 @@ +#include "duk_internal.h" + +#if defined(DUK_USE_FASTINT) + +/* + * Manually optimized double-to-fastint downgrade check. + * + * This check has a large impact on performance, especially for fastint + * slow paths, so must be changed carefully. The code should probably be + * optimized for the case where the result does not fit into a fastint, + * to minimize the penalty for "slow path code" dealing with fractions etc. + * + * At least on one tested soft float ARM platform double-to-int64 coercion + * is very slow (and sometimes produces incorrect results, see self tests). + * This algorithm combines a fastint compatibility check and extracting the + * integer value from an IEEE double for setting the tagged fastint. For + * other platforms a more naive approach might be better. + * + * See doc/fastint.rst for details. + */ + +DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) { + duk_double_union du; + duk_int64_t i; + duk_small_int_t expt; + duk_small_int_t shift; + + /* XXX: optimize for packed duk_tval directly? */ + + du.d = x; + i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du); + expt = (duk_small_int_t) ((i >> 52) & 0x07ff); + shift = expt - 1023; + + if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */ + duk_int64_t t; + + if (((0x000fffffffffffffLL >> shift) & i) == 0) { + t = i | 0x0010000000000000LL; /* implicit leading one */ + t = t & 0x001fffffffffffffLL; + t = t >> (52 - shift); + if (i < 0) { + t = -t; + } + DUK_TVAL_SET_FASTINT(tv, t); + return; + } + } else if (shift == -1023) { /* exponent 0 */ + if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) { + /* Note: reject negative zero. */ + DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0); + return; + } + } else if (shift == 47) { /* exponent 1070 */ + if (i < 0 && (i & 0x000fffffffffffffLL) == 0) { + DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN); + return; + } + } + + DUK_TVAL_SET_DOUBLE(tv, x); + return; +} + +/* + * Manually optimized number-to-double conversion + */ + +#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL) +DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) { + duk_double_union du; + duk_uint64_t t; + + t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv); + if ((t >> 48) != DUK_TAG_FASTINT) { + return tv->d; + } else if (t & 0x0000800000000000ULL) { + t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */ + t = t & 0x0000ffffffffffffULL; /* negative */ + t |= 0xc330000000000000ULL; + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d + 4503599627370496.0; /* 1 << 52 */ + } else if (t != 0) { + t &= 0x0000ffffffffffffULL; /* positive */ + t |= 0x4330000000000000ULL; + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d - 4503599627370496.0; /* 1 << 52 */ + } else { + return 0.0; /* zero */ + } +} +#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */ + +#if 0 /* unused */ +#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL) +DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) { + duk_double_union du; + duk_uint64_t t; + + DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT); + + if (tv->t == DUK_TAG_FASTINT) { + if (tv->v.fi >= 0) { + t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi; + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d - 4503599627370496.0; /* 1 << 52 */ + } else { + t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi); + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d + 4503599627370496.0; /* 1 << 52 */ + } + } else { + return tv->v.d; + } +} +#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */ +#endif /* 0 */ + +#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL) +DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) { + duk_double_union du; + duk_uint64_t t; + + DUK_ASSERT(tv->t == DUK_TAG_FASTINT); + + if (tv->v.fi >= 0) { + t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi; + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d - 4503599627370496.0; /* 1 << 52 */ + } else { + t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi); + DUK_DBLUNION_SET_UINT64(&du, t); + return du.d + 4503599627370496.0; /* 1 << 52 */ + } +} +#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */ + +#endif /* DUK_USE_FASTINT */ |