summaryrefslogtreecommitdiffstats
path: root/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_tval.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_tval.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_tval.c b/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_tval.c
new file mode 100644
index 000000000..a1d0f88f1
--- /dev/null
+++ b/src/civetweb/src/third_party/duktape-1.5.2/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 */