LCOV - code coverage report
Current view: top level - js/public - Conversions.h (source / functions) Hit Total Coverage
Test: output.info Lines: 75 127 59.1 %
Date: 2017-07-14 16:53:18 Functions: 11 29 37.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* ECMAScript conversion operations. */
       8             : 
       9             : #ifndef js_Conversions_h
      10             : #define js_Conversions_h
      11             : 
      12             : #include "mozilla/Casting.h"
      13             : #include "mozilla/FloatingPoint.h"
      14             : #include "mozilla/TypeTraits.h"
      15             : 
      16             : #include <math.h>
      17             : 
      18             : #include "jspubtd.h"
      19             : 
      20             : #include "js/RootingAPI.h"
      21             : #include "js/Value.h"
      22             : 
      23             : struct JSContext;
      24             : 
      25             : namespace js {
      26             : 
      27             : /* DO NOT CALL THIS. Use JS::ToBoolean. */
      28             : extern JS_PUBLIC_API(bool)
      29             : ToBooleanSlow(JS::HandleValue v);
      30             : 
      31             : /* DO NOT CALL THIS.  Use JS::ToNumber. */
      32             : extern JS_PUBLIC_API(bool)
      33             : ToNumberSlow(JSContext* cx, JS::HandleValue v, double* dp);
      34             : 
      35             : /* DO NOT CALL THIS. Use JS::ToInt8. */
      36             : extern JS_PUBLIC_API(bool)
      37             : ToInt8Slow(JSContext *cx, JS::HandleValue v, int8_t *out);
      38             : 
      39             : /* DO NOT CALL THIS. Use JS::ToUint8. */
      40             : extern JS_PUBLIC_API(bool)
      41             : ToUint8Slow(JSContext *cx, JS::HandleValue v, uint8_t *out);
      42             : 
      43             : /* DO NOT CALL THIS. Use JS::ToInt16. */
      44             : extern JS_PUBLIC_API(bool)
      45             : ToInt16Slow(JSContext *cx, JS::HandleValue v, int16_t *out);
      46             : 
      47             : /* DO NOT CALL THIS. Use JS::ToInt32. */
      48             : extern JS_PUBLIC_API(bool)
      49             : ToInt32Slow(JSContext* cx, JS::HandleValue v, int32_t* out);
      50             : 
      51             : /* DO NOT CALL THIS. Use JS::ToUint32. */
      52             : extern JS_PUBLIC_API(bool)
      53             : ToUint32Slow(JSContext* cx, JS::HandleValue v, uint32_t* out);
      54             : 
      55             : /* DO NOT CALL THIS. Use JS::ToUint16. */
      56             : extern JS_PUBLIC_API(bool)
      57             : ToUint16Slow(JSContext* cx, JS::HandleValue v, uint16_t* out);
      58             : 
      59             : /* DO NOT CALL THIS. Use JS::ToInt64. */
      60             : extern JS_PUBLIC_API(bool)
      61             : ToInt64Slow(JSContext* cx, JS::HandleValue v, int64_t* out);
      62             : 
      63             : /* DO NOT CALL THIS. Use JS::ToUint64. */
      64             : extern JS_PUBLIC_API(bool)
      65             : ToUint64Slow(JSContext* cx, JS::HandleValue v, uint64_t* out);
      66             : 
      67             : /* DO NOT CALL THIS. Use JS::ToString. */
      68             : extern JS_PUBLIC_API(JSString*)
      69             : ToStringSlow(JSContext* cx, JS::HandleValue v);
      70             : 
      71             : /* DO NOT CALL THIS. Use JS::ToObject. */
      72             : extern JS_PUBLIC_API(JSObject*)
      73             : ToObjectSlow(JSContext* cx, JS::HandleValue v, bool reportScanStack);
      74             : 
      75             : } // namespace js
      76             : 
      77             : namespace JS {
      78             : 
      79             : namespace detail {
      80             : 
      81             : #ifdef JS_DEBUG
      82             : /**
      83             :  * Assert that we're not doing GC on cx, that we're in a request as
      84             :  * needed, and that the compartments for cx and v are correct.
      85             :  * Also check that GC would be safe at this point.
      86             :  */
      87             : extern JS_PUBLIC_API(void)
      88             : AssertArgumentsAreSane(JSContext* cx, HandleValue v);
      89             : #else
      90             : inline void AssertArgumentsAreSane(JSContext* cx, HandleValue v)
      91             : {}
      92             : #endif /* JS_DEBUG */
      93             : 
      94             : } // namespace detail
      95             : 
      96             : /**
      97             :  * ES6 draft 20141224, 7.1.1, second algorithm.
      98             :  *
      99             :  * Most users shouldn't call this -- use JS::ToBoolean, ToNumber, or ToString
     100             :  * instead.  This will typically only be called from custom convert hooks that
     101             :  * wish to fall back to the ES6 default conversion behavior shared by most
     102             :  * objects in JS, codified as OrdinaryToPrimitive.
     103             :  */
     104             : extern JS_PUBLIC_API(bool)
     105             : OrdinaryToPrimitive(JSContext* cx, HandleObject obj, JSType type, MutableHandleValue vp);
     106             : 
     107             : /* ES6 draft 20141224, 7.1.2. */
     108             : MOZ_ALWAYS_INLINE bool
     109       33756 : ToBoolean(HandleValue v)
     110             : {
     111       33756 :     if (v.isBoolean())
     112       28250 :         return v.toBoolean();
     113        5506 :     if (v.isInt32())
     114         429 :         return v.toInt32() != 0;
     115        5077 :     if (v.isNullOrUndefined())
     116        2747 :         return false;
     117        2330 :     if (v.isDouble()) {
     118           8 :         double d = v.toDouble();
     119           8 :         return !mozilla::IsNaN(d) && d != 0;
     120             :     }
     121        2322 :     if (v.isSymbol())
     122           0 :         return true;
     123             : 
     124             :     /* The slow path handles strings and objects. */
     125        2322 :     return js::ToBooleanSlow(v);
     126             : }
     127             : 
     128             : /* ES6 draft 20141224, 7.1.3. */
     129             : MOZ_ALWAYS_INLINE bool
     130       23079 : ToNumber(JSContext* cx, HandleValue v, double* out)
     131             : {
     132       23079 :     detail::AssertArgumentsAreSane(cx, v);
     133             : 
     134       23079 :     if (v.isNumber()) {
     135       23044 :         *out = v.toNumber();
     136       23044 :         return true;
     137             :     }
     138          35 :     return js::ToNumberSlow(cx, v, out);
     139             : }
     140             : 
     141             : /* ES6 draft 20141224, ToInteger (specialized for doubles). */
     142             : inline double
     143         138 : ToInteger(double d)
     144             : {
     145         138 :     if (d == 0)
     146           0 :         return d;
     147             : 
     148         138 :     if (!mozilla::IsFinite(d)) {
     149           5 :         if (mozilla::IsNaN(d))
     150           5 :             return 0;
     151           0 :         return d;
     152             :     }
     153             : 
     154         133 :     return d < 0 ? ceil(d) : floor(d);
     155             : }
     156             : 
     157             : /* ES6 draft 20141224, 7.1.5. */
     158             : MOZ_ALWAYS_INLINE bool
     159        1941 : ToInt32(JSContext* cx, JS::HandleValue v, int32_t* out)
     160             : {
     161        1941 :     detail::AssertArgumentsAreSane(cx, v);
     162             : 
     163        1941 :     if (v.isInt32()) {
     164        1830 :         *out = v.toInt32();
     165        1830 :         return true;
     166             :     }
     167         111 :     return js::ToInt32Slow(cx, v, out);
     168             : }
     169             : 
     170             : /* ES6 draft 20141224, 7.1.6. */
     171             : MOZ_ALWAYS_INLINE bool
     172         139 : ToUint32(JSContext* cx, HandleValue v, uint32_t* out)
     173             : {
     174         139 :     detail::AssertArgumentsAreSane(cx, v);
     175             : 
     176         139 :     if (v.isInt32()) {
     177         135 :         *out = uint32_t(v.toInt32());
     178         135 :         return true;
     179             :     }
     180           4 :     return js::ToUint32Slow(cx, v, out);
     181             : }
     182             : 
     183             : /* ES6 draft 20141224, 7.1.7. */
     184             : MOZ_ALWAYS_INLINE bool
     185           0 : ToInt16(JSContext *cx, JS::HandleValue v, int16_t *out)
     186             : {
     187           0 :     detail::AssertArgumentsAreSane(cx, v);
     188             : 
     189           0 :     if (v.isInt32()) {
     190           0 :         *out = int16_t(v.toInt32());
     191           0 :         return true;
     192             :     }
     193           0 :     return js::ToInt16Slow(cx, v, out);
     194             : }
     195             : 
     196             : /* ES6 draft 20141224, 7.1.8. */
     197             : MOZ_ALWAYS_INLINE bool
     198           0 : ToUint16(JSContext* cx, HandleValue v, uint16_t* out)
     199             : {
     200           0 :     detail::AssertArgumentsAreSane(cx, v);
     201             : 
     202           0 :     if (v.isInt32()) {
     203           0 :         *out = uint16_t(v.toInt32());
     204           0 :         return true;
     205             :     }
     206           0 :     return js::ToUint16Slow(cx, v, out);
     207             : }
     208             : 
     209             : /* ES6 draft 20141224, 7.1.9 */
     210             : MOZ_ALWAYS_INLINE bool
     211           0 : ToInt8(JSContext *cx, JS::HandleValue v, int8_t *out)
     212             : {
     213           0 :     detail::AssertArgumentsAreSane(cx, v);
     214             : 
     215           0 :     if (v.isInt32()) {
     216           0 :         *out = int8_t(v.toInt32());
     217           0 :         return true;
     218             :     }
     219           0 :     return js::ToInt8Slow(cx, v, out);
     220             : }
     221             : 
     222             : /* ES6 ECMA-262, 7.1.10 */
     223             : MOZ_ALWAYS_INLINE bool
     224           0 : ToUint8(JSContext *cx, JS::HandleValue v, uint8_t *out)
     225             : {
     226           0 :     detail::AssertArgumentsAreSane(cx, v);
     227             : 
     228           0 :     if (v.isInt32()) {
     229           0 :         *out = uint8_t(v.toInt32());
     230           0 :         return true;
     231             :     }
     232           0 :     return js::ToUint8Slow(cx, v, out);
     233             : }
     234             : 
     235             : /*
     236             :  * Non-standard, with behavior similar to that of ToInt32, except in its
     237             :  * producing an int64_t.
     238             :  */
     239             : MOZ_ALWAYS_INLINE bool
     240           0 : ToInt64(JSContext* cx, HandleValue v, int64_t* out)
     241             : {
     242           0 :     detail::AssertArgumentsAreSane(cx, v);
     243             : 
     244           0 :     if (v.isInt32()) {
     245           0 :         *out = int64_t(v.toInt32());
     246           0 :         return true;
     247             :     }
     248           0 :     return js::ToInt64Slow(cx, v, out);
     249             : }
     250             : 
     251             : /*
     252             :  * Non-standard, with behavior similar to that of ToUint32, except in its
     253             :  * producing a uint64_t.
     254             :  */
     255             : MOZ_ALWAYS_INLINE bool
     256           0 : ToUint64(JSContext* cx, HandleValue v, uint64_t* out)
     257             : {
     258           0 :     detail::AssertArgumentsAreSane(cx, v);
     259             : 
     260           0 :     if (v.isInt32()) {
     261           0 :         *out = uint64_t(v.toInt32());
     262           0 :         return true;
     263             :     }
     264           0 :     return js::ToUint64Slow(cx, v, out);
     265             : }
     266             : 
     267             : /* ES6 draft 20141224, 7.1.12. */
     268             : MOZ_ALWAYS_INLINE JSString*
     269        6206 : ToString(JSContext* cx, HandleValue v)
     270             : {
     271        6206 :     detail::AssertArgumentsAreSane(cx, v);
     272             : 
     273        6206 :     if (v.isString())
     274        6178 :         return v.toString();
     275          28 :     return js::ToStringSlow(cx, v);
     276             : }
     277             : 
     278             : /* ES6 draft 20141224, 7.1.13. */
     279             : inline JSObject*
     280        7307 : ToObject(JSContext* cx, HandleValue v)
     281             : {
     282        7307 :     detail::AssertArgumentsAreSane(cx, v);
     283             : 
     284        7307 :     if (v.isObject())
     285        7307 :         return &v.toObject();
     286           0 :     return js::ToObjectSlow(cx, v, false);
     287             : }
     288             : 
     289             : namespace detail {
     290             : 
     291             : /*
     292             :  * Convert a double value to ResultType (an unsigned integral type) using
     293             :  * ECMAScript-style semantics (that is, in like manner to how ECMAScript's
     294             :  * ToInt32 converts to int32_t).
     295             :  *
     296             :  *   If d is infinite or NaN, return 0.
     297             :  *   Otherwise compute d2 = sign(d) * floor(abs(d)), and return the ResultType
     298             :  *   value congruent to d2 mod 2**(bit width of ResultType).
     299             :  *
     300             :  * The algorithm below is inspired by that found in
     301             :  * <http://trac.webkit.org/changeset/67825/trunk/JavaScriptCore/runtime/JSValue.cpp>
     302             :  * but has been generalized to all integer widths.
     303             :  */
     304             : template<typename ResultType>
     305             : inline ResultType
     306        1575 : ToUintWidth(double d)
     307             : {
     308             :     static_assert(mozilla::IsUnsigned<ResultType>::value,
     309             :                   "ResultType must be an unsigned type");
     310             : 
     311        1575 :     uint64_t bits = mozilla::BitwiseCast<uint64_t>(d);
     312        1575 :     unsigned DoubleExponentShift = mozilla::FloatingPoint<double>::kExponentShift;
     313             : 
     314             :     // Extract the exponent component.  (Be careful here!  It's not technically
     315             :     // the exponent in NaN, infinities, and subnormals.)
     316             :     int_fast16_t exp =
     317        1575 :         int_fast16_t((bits & mozilla::FloatingPoint<double>::kExponentBits) >> DoubleExponentShift) -
     318        1575 :         int_fast16_t(mozilla::FloatingPoint<double>::kExponentBias);
     319             : 
     320             :     // If the exponent's less than zero, abs(d) < 1, so the result is 0.  (This
     321             :     // also handles subnormals.)
     322        1575 :     if (exp < 0)
     323         542 :         return 0;
     324             : 
     325        1033 :     uint_fast16_t exponent = mozilla::AssertedCast<uint_fast16_t>(exp);
     326             : 
     327             :     // If the exponent is greater than or equal to the bits of precision of a
     328             :     // double plus ResultType's width, the number is either infinite, NaN, or
     329             :     // too large to have lower-order bits in the congruent value.  (Example:
     330             :     // 2**84 is exactly representable as a double.  The next exact double is
     331             :     // 2**84 + 2**32.  Thus if ResultType is int32_t, an exponent >= 84 implies
     332             :     // floor(abs(d)) == 0 mod 2**32.)  Return 0 in all these cases.
     333        1033 :     const size_t ResultWidth = CHAR_BIT * sizeof(ResultType);
     334        1033 :     if (exponent >= DoubleExponentShift + ResultWidth)
     335           3 :         return 0;
     336             : 
     337             :     // The significand contains the bits that will determine the final result.
     338             :     // Shift those bits left or right, according to the exponent, to their
     339             :     // locations in the unsigned binary representation of floor(abs(d)).
     340             :     static_assert(sizeof(ResultType) <= sizeof(uint64_t),
     341             :                   "Left-shifting below would lose upper bits");
     342        1030 :     ResultType result = (exponent > DoubleExponentShift)
     343        2060 :                         ? ResultType(bits << (exponent - DoubleExponentShift))
     344        2060 :                         : ResultType(bits >> (DoubleExponentShift - exponent));
     345             : 
     346             :     // Two further complications remain.  First, |result| may contain bogus
     347             :     // sign/exponent bits.  Second, IEEE-754 numbers' significands (excluding
     348             :     // subnormals, but we already handled those) have an implicit leading 1
     349             :     // which may affect the final result.
     350             :     //
     351             :     // It may appear that there's complexity here depending on how ResultWidth
     352             :     // and DoubleExponentShift relate, but it turns out there's not.
     353             :     //
     354             :     // Assume ResultWidth < DoubleExponentShift:
     355             :     //   Only right-shifts leave bogus bits in |result|.  For this to happen,
     356             :     //   we must right-shift by > |DoubleExponentShift - ResultWidth|, implying
     357             :     //   |exponent < ResultWidth|.
     358             :     //   The implicit leading bit only matters if it appears in the final
     359             :     //   result -- if |2**exponent mod 2**ResultWidth != 0|.  This implies
     360             :     //   |exponent < ResultWidth|.
     361             :     // Otherwise assume ResultWidth >= DoubleExponentShift:
     362             :     //   Any left-shift less than |ResultWidth - DoubleExponentShift| leaves
     363             :     //   bogus bits in |result|.  This implies |exponent < ResultWidth|.  Any
     364             :     //   right-shift less than |ResultWidth| does too, which implies
     365             :     //   |DoubleExponentShift - ResultWidth < exponent|.  By assumption, then,
     366             :     //   |exponent| is negative, but we excluded that above.  So bogus bits
     367             :     //   need only |exponent < ResultWidth|.
     368             :     //   The implicit leading bit matters identically to the other case, so
     369             :     //   again, |exponent < ResultWidth|.
     370        1030 :     if (exponent < ResultWidth) {
     371        1030 :         ResultType implicitOne = ResultType(1) << exponent;
     372        1030 :         result &= implicitOne - 1; // remove bogus bits
     373        1030 :         result += implicitOne; // add the implicit bit
     374             :     }
     375             : 
     376             :     // Compute the congruent value in the signed range.
     377        1030 :     return (bits & mozilla::FloatingPoint<double>::kSignBit) ? ~result + 1 : result;
     378             : }
     379             : 
     380             : template<typename ResultType>
     381             : inline ResultType
     382         123 : ToIntWidth(double d)
     383             : {
     384             :     static_assert(mozilla::IsSigned<ResultType>::value,
     385             :                   "ResultType must be a signed type");
     386             : 
     387         123 :     const ResultType MaxValue = (1ULL << (CHAR_BIT * sizeof(ResultType) - 1)) - 1;
     388         123 :     const ResultType MinValue = -MaxValue - 1;
     389             : 
     390             :     typedef typename mozilla::MakeUnsigned<ResultType>::Type UnsignedResult;
     391         123 :     UnsignedResult u = ToUintWidth<UnsignedResult>(d);
     392         123 :     if (u <= UnsignedResult(MaxValue))
     393         121 :         return static_cast<ResultType>(u);
     394           2 :     return (MinValue + static_cast<ResultType>(u - MaxValue)) - 1;
     395             : }
     396             : 
     397             : } // namespace detail
     398             : 
     399             : /* ES5 9.5 ToInt32 (specialized for doubles). */
     400             : inline int32_t
     401         123 : ToInt32(double d)
     402             : {
     403             :     // clang crashes compiling this when targeting arm:
     404             :     // https://llvm.org/bugs/show_bug.cgi?id=22974
     405             : #if defined (__arm__) && defined (__GNUC__) && !defined(__clang__)
     406             :     int32_t i;
     407             :     uint32_t    tmp0;
     408             :     uint32_t    tmp1;
     409             :     uint32_t    tmp2;
     410             :     asm (
     411             :     // We use a pure integer solution here. In the 'softfp' ABI, the argument
     412             :     // will start in r0 and r1, and VFP can't do all of the necessary ECMA
     413             :     // conversions by itself so some integer code will be required anyway. A
     414             :     // hybrid solution is faster on A9, but this pure integer solution is
     415             :     // notably faster for A8.
     416             : 
     417             :     // %0 is the result register, and may alias either of the %[QR]1 registers.
     418             :     // %Q4 holds the lower part of the mantissa.
     419             :     // %R4 holds the sign, exponent, and the upper part of the mantissa.
     420             :     // %1, %2 and %3 are used as temporary values.
     421             : 
     422             :     // Extract the exponent.
     423             : "   mov     %1, %R4, LSR #20\n"
     424             : "   bic     %1, %1, #(1 << 11)\n"  // Clear the sign.
     425             : 
     426             :     // Set the implicit top bit of the mantissa. This clobbers a bit of the
     427             :     // exponent, but we have already extracted that.
     428             : "   orr     %R4, %R4, #(1 << 20)\n"
     429             : 
     430             :     // Special Cases
     431             :     //   We should return zero in the following special cases:
     432             :     //    - Exponent is 0x000 - 1023: +/-0 or subnormal.
     433             :     //    - Exponent is 0x7ff - 1023: +/-INFINITY or NaN
     434             :     //      - This case is implicitly handled by the standard code path anyway,
     435             :     //        as shifting the mantissa up by the exponent will result in '0'.
     436             :     //
     437             :     // The result is composed of the mantissa, prepended with '1' and
     438             :     // bit-shifted left by the (decoded) exponent. Note that because the r1[20]
     439             :     // is the bit with value '1', r1 is effectively already shifted (left) by
     440             :     // 20 bits, and r0 is already shifted by 52 bits.
     441             : 
     442             :     // Adjust the exponent to remove the encoding offset. If the decoded
     443             :     // exponent is negative, quickly bail out with '0' as such values round to
     444             :     // zero anyway. This also catches +/-0 and subnormals.
     445             : "   sub     %1, %1, #0xff\n"
     446             : "   subs    %1, %1, #0x300\n"
     447             : "   bmi     8f\n"
     448             : 
     449             :     //  %1 = (decoded) exponent >= 0
     450             :     //  %R4 = upper mantissa and sign
     451             : 
     452             :     // ---- Lower Mantissa ----
     453             : "   subs    %3, %1, #52\n"         // Calculate exp-52
     454             : "   bmi     1f\n"
     455             : 
     456             :     // Shift r0 left by exp-52.
     457             :     // Ensure that we don't overflow ARM's 8-bit shift operand range.
     458             :     // We need to handle anything up to an 11-bit value here as we know that
     459             :     // 52 <= exp <= 1024 (0x400). Any shift beyond 31 bits results in zero
     460             :     // anyway, so as long as we don't touch the bottom 5 bits, we can use
     461             :     // a logical OR to push long shifts into the 32 <= (exp&0xff) <= 255 range.
     462             : "   bic     %2, %3, #0xff\n"
     463             : "   orr     %3, %3, %2, LSR #3\n"
     464             :     // We can now perform a straight shift, avoiding the need for any
     465             :     // conditional instructions or extra branches.
     466             : "   mov     %Q4, %Q4, LSL %3\n"
     467             : "   b       2f\n"
     468             : "1:\n" // Shift r0 right by 52-exp.
     469             :     // We know that 0 <= exp < 52, and we can shift up to 255 bits so 52-exp
     470             :     // will always be a valid shift and we can sk%3 the range check for this case.
     471             : "   rsb     %3, %1, #52\n"
     472             : "   mov     %Q4, %Q4, LSR %3\n"
     473             : 
     474             :     //  %1 = (decoded) exponent
     475             :     //  %R4 = upper mantissa and sign
     476             :     //  %Q4 = partially-converted integer
     477             : 
     478             : "2:\n"
     479             :     // ---- Upper Mantissa ----
     480             :     // This is much the same as the lower mantissa, with a few different
     481             :     // boundary checks and some masking to hide the exponent & sign bit in the
     482             :     // upper word.
     483             :     // Note that the upper mantissa is pre-shifted by 20 in %R4, but we shift
     484             :     // it left more to remove the sign and exponent so it is effectively
     485             :     // pre-shifted by 31 bits.
     486             : "   subs    %3, %1, #31\n"          // Calculate exp-31
     487             : "   mov     %1, %R4, LSL #11\n"     // Re-use %1 as a temporary register.
     488             : "   bmi     3f\n"
     489             : 
     490             :     // Shift %R4 left by exp-31.
     491             :     // Avoid overflowing the 8-bit shift range, as before.
     492             : "   bic     %2, %3, #0xff\n"
     493             : "   orr     %3, %3, %2, LSR #3\n"
     494             :     // Perform the shift.
     495             : "   mov     %2, %1, LSL %3\n"
     496             : "   b       4f\n"
     497             : "3:\n" // Shift r1 right by 31-exp.
     498             :     // We know that 0 <= exp < 31, and we can shift up to 255 bits so 31-exp
     499             :     // will always be a valid shift and we can skip the range check for this case.
     500             : "   rsb     %3, %3, #0\n"          // Calculate 31-exp from -(exp-31)
     501             : "   mov     %2, %1, LSR %3\n"      // Thumb-2 can't do "LSR %3" in "orr".
     502             : 
     503             :     //  %Q4 = partially-converted integer (lower)
     504             :     //  %R4 = upper mantissa and sign
     505             :     //  %2 = partially-converted integer (upper)
     506             : 
     507             : "4:\n"
     508             :     // Combine the converted parts.
     509             : "   orr     %Q4, %Q4, %2\n"
     510             :     // Negate the result if we have to, and move it to %0 in the process. To
     511             :     // avoid conditionals, we can do this by inverting on %R4[31], then adding
     512             :     // %R4[31]>>31.
     513             : "   eor     %Q4, %Q4, %R4, ASR #31\n"
     514             : "   add     %0, %Q4, %R4, LSR #31\n"
     515             : "   b       9f\n"
     516             : "8:\n"
     517             :     // +/-INFINITY, +/-0, subnormals, NaNs, and anything else out-of-range that
     518             :     // will result in a conversion of '0'.
     519             : "   mov     %0, #0\n"
     520             : "9:\n"
     521             :     : "=r" (i), "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2), "=&r" (d)
     522             :     : "4" (d)
     523             :     : "cc"
     524             :         );
     525             :     return i;
     526             : #else
     527         123 :     return detail::ToIntWidth<int32_t>(d);
     528             : #endif
     529             : }
     530             : 
     531             : /* ES5 9.6 (specialized for doubles). */
     532             : inline uint32_t
     533        1452 : ToUint32(double d)
     534             : {
     535        1452 :     return detail::ToUintWidth<uint32_t>(d);
     536             : }
     537             : 
     538             : /* WEBIDL 4.2.4 */
     539             : inline int8_t
     540           0 : ToInt8(double d)
     541             : {
     542           0 :     return detail::ToIntWidth<int8_t>(d);
     543             : }
     544             : 
     545             : /* ECMA-262 7.1.10 ToUInt8() specialized for doubles. */
     546             : inline int8_t
     547           0 : ToUint8(double d)
     548             : {
     549           0 :     return detail::ToUintWidth<uint8_t>(d);
     550             : }
     551             : 
     552             : /* WEBIDL 4.2.6 */
     553             : inline int16_t
     554           0 : ToInt16(double d)
     555             : {
     556           0 :     return detail::ToIntWidth<int16_t>(d);
     557             : }
     558             : 
     559             : inline uint16_t
     560           0 : ToUint16(double d)
     561             : {
     562           0 :     return detail::ToUintWidth<uint16_t>(d);
     563             : }
     564             : 
     565             : /* WEBIDL 4.2.10 */
     566             : inline int64_t
     567           0 : ToInt64(double d)
     568             : {
     569           0 :     return detail::ToIntWidth<int64_t>(d);
     570             : }
     571             : 
     572             : /* WEBIDL 4.2.11 */
     573             : inline uint64_t
     574           0 : ToUint64(double d)
     575             : {
     576           0 :     return detail::ToUintWidth<uint64_t>(d);
     577             : }
     578             : 
     579             : } // namespace JS
     580             : 
     581             : #endif /* js_Conversions_h */

Generated by: LCOV version 1.13