LCOV - code coverage report
Current view: top level - js/src - jsnum.h (source / functions) Hit Total Coverage
Test: output.info Lines: 35 44 79.5 %
Date: 2017-07-14 16:53:18 Functions: 7 8 87.5 %
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             : #ifndef jsnum_h
       8             : #define jsnum_h
       9             : 
      10             : #include "mozilla/FloatingPoint.h"
      11             : #include "mozilla/Range.h"
      12             : 
      13             : #include "NamespaceImports.h"
      14             : 
      15             : #include "js/Conversions.h"
      16             : 
      17             : #include "vm/String.h"
      18             : 
      19             : 
      20             : // This macro is should be `one' if current compiler supports builtin functions
      21             : // like __builtin_sadd_overflow.
      22             : #if __GNUC__ >= 5
      23             :     // GCC 5 and above supports these functions.
      24             :     #define BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(x) 1
      25             : #else
      26             :     // For CLANG, we use its own function to check for this.
      27             :     #ifdef __has_builtin
      28             :         #define BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(x) __has_builtin(x)
      29             :     #endif
      30             : #endif
      31             : #ifndef BUILTIN_CHECKED_ARITHMETIC_SUPPORTED
      32             :     #define BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(x) 0
      33             : #endif
      34             : 
      35             : namespace js {
      36             : 
      37             : class StringBuffer;
      38             : 
      39             : extern MOZ_MUST_USE bool
      40             : InitRuntimeNumberState(JSRuntime* rt);
      41             : 
      42             : #if !EXPOSE_INTL_API
      43             : extern void
      44             : FinishRuntimeNumberState(JSRuntime* rt);
      45             : #endif
      46             : 
      47             : /* Initialize the Number class, returning its prototype object. */
      48             : extern JSObject*
      49             : InitNumberClass(JSContext* cx, HandleObject obj);
      50             : 
      51             : } /* namespace js */
      52             : 
      53             : /*
      54             :  * String constants for global function names, used in jsapi.c and jsnum.c.
      55             :  */
      56             : extern const char js_isNaN_str[];
      57             : extern const char js_isFinite_str[];
      58             : extern const char js_parseFloat_str[];
      59             : extern const char js_parseInt_str[];
      60             : 
      61             : class JSAtom;
      62             : 
      63             : namespace js {
      64             : 
      65             : /*
      66             :  * When base == 10, this function implements ToString() as specified by
      67             :  * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
      68             :  * performance.  See also js::NumberToCString().
      69             :  */
      70             : template <AllowGC allowGC>
      71             : extern JSString*
      72             : NumberToString(JSContext* cx, double d);
      73             : 
      74             : extern JSAtom*
      75             : NumberToAtom(JSContext* cx, double d);
      76             : 
      77             : template <AllowGC allowGC>
      78             : extern JSFlatString*
      79             : Int32ToString(JSContext* cx, int32_t i);
      80             : 
      81             : extern JSAtom*
      82             : Int32ToAtom(JSContext* cx, int32_t si);
      83             : 
      84             : /*
      85             :  * Convert an integer or double (contained in the given value) to a string and
      86             :  * append to the given buffer.
      87             :  */
      88             : extern MOZ_MUST_USE bool JS_FASTCALL
      89             : NumberValueToStringBuffer(JSContext* cx, const Value& v, StringBuffer& sb);
      90             : 
      91             : /* Same as js_NumberToString, different signature. */
      92             : extern JSFlatString*
      93             : NumberToString(JSContext* cx, double d);
      94             : 
      95             : extern JSFlatString*
      96             : IndexToString(JSContext* cx, uint32_t index);
      97             : 
      98             : /*
      99             :  * Usually a small amount of static storage is enough, but sometimes we need
     100             :  * to dynamically allocate much more.  This struct encapsulates that.
     101             :  * Dynamically allocated memory will be freed when the object is destroyed.
     102             :  */
     103             : struct ToCStringBuf
     104             : {
     105             :     /*
     106             :      * The longest possible result that would need to fit in sbuf is
     107             :      * (-0x80000000).toString(2), which has length 33.  Longer cases are
     108             :      * possible, but they'll go in dbuf.
     109             :      */
     110             :     static const size_t sbufSize = 34;
     111             :     char sbuf[sbufSize];
     112             :     char* dbuf;
     113             : 
     114             :     ToCStringBuf();
     115             :     ~ToCStringBuf();
     116             : };
     117             : 
     118             : /*
     119             :  * Convert a number to a C string.  When base==10, this function implements
     120             :  * ToString() as specified by ECMA-262-5 section 9.8.1.  It handles integral
     121             :  * values cheaply.  Return nullptr if we ran out of memory.  See also
     122             :  * NumberToCString().
     123             :  */
     124             : extern char*
     125             : NumberToCString(JSContext* cx, ToCStringBuf* cbuf, double d, int base = 10);
     126             : 
     127             : /*
     128             :  * The largest positive integer such that all positive integers less than it
     129             :  * may be precisely represented using the IEEE-754 double-precision format.
     130             :  */
     131             : const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53;
     132             : 
     133             : /*
     134             :  * Parse a decimal number encoded in |chars|.  The decimal number must be
     135             :  * sufficiently small that it will not overflow the integrally-precise range of
     136             :  * the double type -- that is, the number will be smaller than
     137             :  * DOUBLE_INTEGRAL_PRECISION_LIMIT
     138             :  */
     139             : template <typename CharT>
     140             : extern double
     141             : ParseDecimalNumber(const mozilla::Range<const CharT> chars);
     142             : 
     143             : /*
     144             :  * Compute the positive integer of the given base described immediately at the
     145             :  * start of the range [start, end) -- no whitespace-skipping, no magical
     146             :  * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just
     147             :  * reading the digits of the integer.  Return the index one past the end of the
     148             :  * digits of the integer in *endp, and return the integer itself in *dp.  If
     149             :  * base is 10 or a power of two the returned integer is the closest possible
     150             :  * double; otherwise extremely large integers may be slightly inaccurate.
     151             :  *
     152             :  * If [start, end) does not begin with a number with the specified base,
     153             :  * *dp == 0 and *endp == start upon return.
     154             :  */
     155             : template <typename CharT>
     156             : extern MOZ_MUST_USE bool
     157             : GetPrefixInteger(JSContext* cx, const CharT* start, const CharT* end, int base,
     158             :                  const CharT** endp, double* dp);
     159             : 
     160             : /*
     161             :  * This is like GetPrefixInteger, but only deals with base 10, and doesn't have
     162             :  * and |endp| outparam.  It should only be used when the characters are known to
     163             :  * only contain digits.
     164             :  */
     165             : extern MOZ_MUST_USE bool
     166             : GetDecimalInteger(JSContext* cx, const char16_t* start, const char16_t* end, double* dp);
     167             : 
     168             : extern MOZ_MUST_USE bool
     169             : StringToNumber(JSContext* cx, JSString* str, double* result);
     170             : 
     171             : /* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
     172             : MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
     173         806 : ToNumber(JSContext* cx, JS::MutableHandleValue vp)
     174             : {
     175         806 :     if (vp.isNumber())
     176         688 :         return true;
     177             :     double d;
     178             :     extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext* cx, HandleValue v, double* dp);
     179         118 :     if (!ToNumberSlow(cx, vp, &d))
     180           0 :         return false;
     181             : 
     182         118 :     vp.setNumber(d);
     183         118 :     return true;
     184             : }
     185             : 
     186             : MOZ_MUST_USE bool
     187             : num_parseInt(JSContext* cx, unsigned argc, Value* vp);
     188             : 
     189             : }  /* namespace js */
     190             : 
     191             : /*
     192             :  * Similar to strtod except that it replaces overflows with infinities of the
     193             :  * correct sign, and underflows with zeros of the correct sign.  Guaranteed to
     194             :  * return the closest double number to the given input in dp.
     195             :  *
     196             :  * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
     197             :  * the appropriate sign.  The case of the "Infinity" string must match exactly.
     198             :  * If the string does not contain a number, set *dEnd to begin and return 0.0
     199             :  * in *d.
     200             :  *
     201             :  * Return false if out of memory.
     202             :  */
     203             : template <typename CharT>
     204             : extern MOZ_MUST_USE bool
     205             : js_strtod(JSContext* cx, const CharT* begin, const CharT* end,
     206             :           const CharT** dEnd, double* d);
     207             : 
     208             : namespace js {
     209             : 
     210             : extern MOZ_MUST_USE bool
     211             : num_toString(JSContext* cx, unsigned argc, Value* vp);
     212             : 
     213             : extern MOZ_MUST_USE bool
     214             : num_valueOf(JSContext* cx, unsigned argc, Value* vp);
     215             : 
     216             : static MOZ_ALWAYS_INLINE bool
     217        2620 : ValueFitsInInt32(const Value& v, int32_t* pi)
     218             : {
     219        2620 :     if (v.isInt32()) {
     220        1359 :         *pi = v.toInt32();
     221        1359 :         return true;
     222             :     }
     223        1261 :     return v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), pi);
     224             : }
     225             : 
     226             : /*
     227             :  * Returns true if the given value is definitely an index: that is, the value
     228             :  * is a number that's an unsigned 32-bit integer.
     229             :  *
     230             :  * This method prioritizes common-case speed over accuracy in every case.  It
     231             :  * can produce false negatives (but not false positives): some values which are
     232             :  * indexes will be reported not to be indexes by this method.  Users must
     233             :  * consider this possibility when using this method.
     234             :  */
     235             : static MOZ_ALWAYS_INLINE bool
     236        4957 : IsDefinitelyIndex(const Value& v, uint32_t* indexp)
     237             : {
     238        4957 :     if (v.isInt32() && v.toInt32() >= 0) {
     239        1536 :         *indexp = v.toInt32();
     240        1536 :         return true;
     241             :     }
     242             : 
     243             :     int32_t i;
     244        3421 :     if (v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), &i) && i >= 0) {
     245           0 :         *indexp = uint32_t(i);
     246           0 :         return true;
     247             :     }
     248             : 
     249        3421 :     if (v.isString() && v.toString()->hasIndexValue()) {
     250           4 :         *indexp = v.toString()->getIndexValue();
     251           4 :         return true;
     252             :     }
     253             : 
     254        3417 :     return false;
     255             : }
     256             : 
     257             : /* ES5 9.4 ToInteger. */
     258             : static MOZ_MUST_USE inline bool
     259        5615 : ToInteger(JSContext* cx, HandleValue v, double* dp)
     260             : {
     261        5615 :     if (v.isInt32()) {
     262        5610 :         *dp = v.toInt32();
     263        5610 :         return true;
     264             :     }
     265           5 :     if (v.isDouble()) {
     266           0 :         *dp = v.toDouble();
     267           5 :     } else if (v.isString() && v.toString()->hasIndexValue()) {
     268           0 :         *dp = v.toString()->getIndexValue();
     269           0 :         return true;
     270             :     } else {
     271             :         extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext* cx, HandleValue v, double* dp);
     272           5 :         if (!ToNumberSlow(cx, v, dp))
     273           0 :             return false;
     274             :     }
     275           5 :     *dp = JS::ToInteger(*dp);
     276           5 :     return true;
     277             : }
     278             : 
     279             : /* ES2017 draft 7.1.17 ToIndex
     280             :  *
     281             :  * Return true and set |*index| to the integer value if |v| is a valid
     282             :  * integer index value. Otherwise report a RangeError and return false.
     283             :  *
     284             :  * The returned index will always be in the range 0 <= *index <= 2^53-1.
     285             :  */
     286             : MOZ_MUST_USE bool
     287             : ToIndex(JSContext* cx, JS::HandleValue v, const unsigned errorNumber, uint64_t* index);
     288             : 
     289             : static MOZ_MUST_USE inline bool
     290           0 : ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index)
     291             : {
     292           0 :     return ToIndex(cx, v, JSMSG_BAD_INDEX, index);
     293             : }
     294             : 
     295             : MOZ_MUST_USE inline bool
     296        1296 : SafeAdd(int32_t one, int32_t two, int32_t* res)
     297             : {
     298             : #if BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(__builtin_sadd_overflow)
     299             :     // Using compiler's builtin function.
     300        1296 :     return !__builtin_sadd_overflow(one, two, res);
     301             : #else
     302             :     // Use unsigned for the 32-bit operation since signed overflow gets
     303             :     // undefined behavior.
     304             :     *res = uint32_t(one) + uint32_t(two);
     305             :     int64_t ores = (int64_t)one + (int64_t)two;
     306             :     return ores == (int64_t)*res;
     307             : #endif
     308             : }
     309             : 
     310             : MOZ_MUST_USE inline bool
     311          16 : SafeSub(int32_t one, int32_t two, int32_t* res)
     312             : {
     313             : #if BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(__builtin_ssub_overflow)
     314          16 :     return !__builtin_ssub_overflow(one, two, res);
     315             : #else
     316             :     *res = uint32_t(one) - uint32_t(two);
     317             :     int64_t ores = (int64_t)one - (int64_t)two;
     318             :     return ores == (int64_t)*res;
     319             : #endif
     320             : }
     321             : 
     322             : MOZ_MUST_USE inline bool
     323          15 : SafeMul(int32_t one, int32_t two, int32_t* res)
     324             : {
     325             : #if BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(__builtin_smul_overflow)
     326          15 :     return !__builtin_smul_overflow(one, two, res);
     327             : #else
     328             :     *res = uint32_t(one) * uint32_t(two);
     329             :     int64_t ores = (int64_t)one * (int64_t)two;
     330             :     return ores == (int64_t)*res;
     331             : #endif
     332             : }
     333             : 
     334             : } /* namespace js */
     335             : 
     336             : #endif /* jsnum_h */

Generated by: LCOV version 1.13