]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_tval.c
buildsys: switch source download to quincy
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.8.0 / src-separate / duk_tval.c
1 #include "duk_internal.h"
2
3 #if defined(DUK_USE_FASTINT)
4
5 /*
6 * Manually optimized double-to-fastint downgrade check.
7 *
8 * This check has a large impact on performance, especially for fastint
9 * slow paths, so must be changed carefully. The code should probably be
10 * optimized for the case where the result does not fit into a fastint,
11 * to minimize the penalty for "slow path code" dealing with fractions etc.
12 *
13 * At least on one tested soft float ARM platform double-to-int64 coercion
14 * is very slow (and sometimes produces incorrect results, see self tests).
15 * This algorithm combines a fastint compatibility check and extracting the
16 * integer value from an IEEE double for setting the tagged fastint. For
17 * other platforms a more naive approach might be better.
18 *
19 * See doc/fastint.rst for details.
20 */
21
22 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
23 duk_double_union du;
24 duk_int64_t i;
25 duk_small_int_t expt;
26 duk_small_int_t shift;
27
28 /* XXX: optimize for packed duk_tval directly? */
29
30 du.d = x;
31 i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
32 expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
33 shift = expt - 1023;
34
35 if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
36 duk_int64_t t;
37
38 if (((0x000fffffffffffffLL >> shift) & i) == 0) {
39 t = i | 0x0010000000000000LL; /* implicit leading one */
40 t = t & 0x001fffffffffffffLL;
41 t = t >> (52 - shift);
42 if (i < 0) {
43 t = -t;
44 }
45 DUK_TVAL_SET_FASTINT(tv, t);
46 return;
47 }
48 } else if (shift == -1023) { /* exponent 0 */
49 if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
50 /* Note: reject negative zero. */
51 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
52 return;
53 }
54 } else if (shift == 47) { /* exponent 1070 */
55 if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
56 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
57 return;
58 }
59 }
60
61 DUK_TVAL_SET_DOUBLE(tv, x);
62 return;
63 }
64
65 /*
66 * Manually optimized number-to-double conversion
67 */
68
69 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
70 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
71 duk_double_union du;
72 duk_uint64_t t;
73
74 t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
75 if ((t >> 48) != DUK_TAG_FASTINT) {
76 return tv->d;
77 } else if (t & 0x0000800000000000ULL) {
78 t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
79 t = t & 0x0000ffffffffffffULL; /* negative */
80 t |= 0xc330000000000000ULL;
81 DUK_DBLUNION_SET_UINT64(&du, t);
82 return du.d + 4503599627370496.0; /* 1 << 52 */
83 } else if (t != 0) {
84 t &= 0x0000ffffffffffffULL; /* positive */
85 t |= 0x4330000000000000ULL;
86 DUK_DBLUNION_SET_UINT64(&du, t);
87 return du.d - 4503599627370496.0; /* 1 << 52 */
88 } else {
89 return 0.0; /* zero */
90 }
91 }
92 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
93
94 #if 0 /* unused */
95 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
96 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
97 duk_double_union du;
98 duk_uint64_t t;
99
100 DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
101
102 if (tv->t == DUK_TAG_FASTINT) {
103 if (tv->v.fi >= 0) {
104 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
105 DUK_DBLUNION_SET_UINT64(&du, t);
106 return du.d - 4503599627370496.0; /* 1 << 52 */
107 } else {
108 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
109 DUK_DBLUNION_SET_UINT64(&du, t);
110 return du.d + 4503599627370496.0; /* 1 << 52 */
111 }
112 } else {
113 return tv->v.d;
114 }
115 }
116 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
117 #endif /* 0 */
118
119 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
120 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
121 duk_double_union du;
122 duk_uint64_t t;
123
124 DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
125
126 if (tv->v.fi >= 0) {
127 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
128 DUK_DBLUNION_SET_UINT64(&du, t);
129 return du.d - 4503599627370496.0; /* 1 << 52 */
130 } else {
131 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
132 DUK_DBLUNION_SET_UINT64(&du, t);
133 return du.d + 4503599627370496.0; /* 1 << 52 */
134 }
135 }
136 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
137
138 #endif /* DUK_USE_FASTINT */