1/*
2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <cmath>
29#include <wtf/Optional.h>
30
31namespace JSC {
32
33const int32_t maxExponentForIntegerMathPow = 1000;
34double JIT_OPERATION operationMathPow(double x, double y) WTF_INTERNAL;
35int32_t JIT_OPERATION operationToInt32(double) WTF_INTERNAL;
36int32_t JIT_OPERATION operationToInt32SensibleSlow(double) WTF_INTERNAL;
37
38constexpr double maxSafeInteger()
39{
40 // 2 ^ 53 - 1
41 return 9007199254740991.0;
42}
43
44constexpr double minSafeInteger()
45{
46 // -(2 ^ 53 - 1)
47 return -9007199254740991.0;
48}
49
50// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
51// Note that this operation is identical to ToUInt32 other than to interpretation
52// of the resulting bit-pattern (as such this method is also called to implement
53// ToUInt32).
54//
55// The operation can be described as round towards zero, then select the 32 least
56// bits of the resulting value in 2s-complement representation.
57enum ToInt32Mode {
58 Generic,
59 AfterSensibleConversionAttempt,
60};
61template<ToInt32Mode Mode>
62ALWAYS_INLINE int32_t toInt32Internal(double number)
63{
64 uint64_t bits = WTF::bitwise_cast<uint64_t>(number);
65 int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff;
66
67 // If exponent < 0 there will be no bits to the left of the decimal point
68 // after rounding; if the exponent is > 83 then no bits of precision can be
69 // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits
70 // of fractional precision).
71 // Note this case handles 0, -0, and all infinite, NaN, & denormal value.
72
73 // We need to check exp > 83 because:
74 // 1. exp may be used as a left shift value below in (exp - 52), and
75 // 2. Left shift amounts that exceed 31 results in undefined behavior. See:
76 // http://en.cppreference.com/w/cpp/language/operator_arithmetic#Bitwise_shift_operators
77 //
78 // Using an unsigned comparison here also gives us a exp < 0 check for free.
79 if (static_cast<uint32_t>(exp) > 83u)
80 return 0;
81
82 // Select the appropriate 32-bits from the floating point mantissa. If the
83 // exponent is 52 then the bits we need to select are already aligned to the
84 // lowest bits of the 64-bit integer representation of the number, no need
85 // to shift. If the exponent is greater than 52 we need to shift the value
86 // left by (exp - 52), if the value is less than 52 we need to shift right
87 // accordingly.
88 uint32_t result = (exp > 52)
89 ? static_cast<uint32_t>(bits << (exp - 52))
90 : static_cast<uint32_t>(bits >> (52 - exp));
91
92 // IEEE-754 double precision values are stored omitting an implicit 1 before
93 // the decimal point; we need to reinsert this now. We may also the shifted
94 // invalid bits into the result that are not a part of the mantissa (the sign
95 // and exponent bits from the floatingpoint representation); mask these out.
96 // Note that missingOne should be held as uint32_t since ((1 << 31) - 1) causes
97 // int32_t overflow.
98 if (Mode == ToInt32Mode::AfterSensibleConversionAttempt) {
99 if (exp == 31) {
100 // This is an optimization for when toInt32() is called in the slow path
101 // of a JIT operation. Currently, this optimization is only applicable for
102 // x86 ports. This optimization offers 5% performance improvement in
103 // kraken-crypto-pbkdf2.
104 //
105 // On x86, the fast path does a sensible double-to-int32 conversion, by
106 // first attempting to truncate the double value to int32 using the
107 // cvttsd2si_rr instruction. According to Intel's manual, cvttsd2si performs
108 // the following truncate operation:
109 //
110 // If src = NaN, +-Inf, or |(src)rz| > 0x7fffffff and (src)rz != 0x80000000,
111 // then the result becomes 0x80000000. Otherwise, the operation succeeds.
112 //
113 // Note that the ()rz notation means rounding towards zero.
114 // We'll call the slow case function only when the above cvttsd2si fails. The
115 // JIT code checks for fast path failure by checking if result == 0x80000000.
116 // Hence, the slow path will only see the following possible set of numbers:
117 //
118 // NaN, +-Inf, or |(src)rz| > 0x7fffffff.
119 //
120 // As a result, the exp of the double is always >= 31. We can take advantage
121 // of this by specifically checking for (exp == 31) and give the compiler a
122 // chance to constant fold the operations below.
123 const constexpr uint32_t missingOne = 1U << 31;
124 result &= missingOne - 1;
125 result += missingOne;
126 }
127 } else {
128 if (exp < 32) {
129 const uint32_t missingOne = 1U << exp;
130 result &= missingOne - 1;
131 result += missingOne;
132 }
133 }
134
135 // If the input value was negative (we could test either 'number' or 'bits',
136 // but testing 'bits' is likely faster) invert the result appropriately.
137 return static_cast<int64_t>(bits) < 0 ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
138}
139
140ALWAYS_INLINE int32_t toInt32(double number)
141{
142#if HAVE(FJCVTZS_INSTRUCTION)
143 int32_t result = 0;
144 __asm__ ("fjcvtzs %w0, %d1" : "=r" (result) : "w" (number) : "cc");
145 return result;
146#else
147 return toInt32Internal<ToInt32Mode::Generic>(number);
148#endif
149}
150
151// This implements ToUInt32, defined in ECMA-262 9.6.
152inline uint32_t toUInt32(double number)
153{
154 // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
155 // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
156 return toInt32(number);
157}
158
159inline Optional<double> safeReciprocalForDivByConst(double constant)
160{
161 // No "weird" numbers (NaN, Denormal, etc).
162 if (!constant || !std::isnormal(constant))
163 return WTF::nullopt;
164
165 int exponent;
166 if (std::frexp(constant, &exponent) != 0.5)
167 return WTF::nullopt;
168
169 // Note that frexp() returns the value divided by two
170 // so we to offset this exponent by one.
171 exponent -= 1;
172
173 // A double exponent is between -1022 and 1023.
174 // Nothing we can do to invert 1023.
175 if (exponent == 1023)
176 return WTF::nullopt;
177
178 double reciprocal = std::ldexp(1, -exponent);
179 ASSERT(std::isnormal(reciprocal));
180 ASSERT(1. / constant == reciprocal);
181 ASSERT(constant == 1. / reciprocal);
182 ASSERT(1. == constant * reciprocal);
183
184 return reciprocal;
185}
186
187ALWAYS_INLINE bool canBeStrictInt32(double value)
188{
189 // Note: while this behavior is undefined for NaN and inf, the subsequent statement will catch these cases.
190 const int32_t asInt32 = static_cast<int32_t>(value);
191 return !(asInt32 != value || (!asInt32 && std::signbit(value))); // true for -0.0
192}
193
194ALWAYS_INLINE bool canBeInt32(double value)
195{
196 // Note: Strictly speaking this is an undefined behavior.
197 return static_cast<int32_t>(value) == value;
198}
199
200extern "C" {
201double JIT_OPERATION jsRound(double value) REFERENCED_FROM_ASM WTF_INTERNAL;
202
203// On Windows we need to wrap fmod; on other platforms we can call it directly.
204// On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
205#if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
206double JIT_OPERATION jsMod(double x, double y) REFERENCED_FROM_ASM WTF_INTERNAL;
207#else
208#define jsMod fmod
209#endif
210}
211
212namespace Math {
213
214using std::sin;
215using std::sinh;
216using std::cos;
217using std::cosh;
218using std::tan;
219using std::tanh;
220using std::asin;
221using std::asinh;
222using std::acos;
223using std::acosh;
224using std::atan;
225using std::atanh;
226using std::log;
227using std::log10;
228using std::log2;
229using std::cbrt;
230using std::exp;
231using std::expm1;
232
233double JIT_OPERATION log1p(double) WTF_INTERNAL;
234
235} // namespace Math
236} // namespace JSC
237