LCOV - app.info - js/src/jsutil.h

LCOV - code coverage report
| Current view: | directory - js/src - jsutil.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 93 | 92 | 98.9 %
| Date: | 2012-04-07 | Functions: | 108 | 98 | 90.7 %

           1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla Communicator client code, released
          17                 :  * March 31, 1998.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Netscape Communications Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : /*
          41                 :  * PR assertion checker.
          42                 :  */
          43                 :
          44                 : #ifndef jsutil_h___
          45                 : #define jsutil_h___
          46                 :
          47                 : #include "mozilla/Attributes.h"
          48                 :
          49                 : #include "js/Utility.h"
          50                 :
          51                 : /* Forward declarations. */
          52                 : struct JSContext;
          53                 :
          54                 : static JS_ALWAYS_INLINE void *
          55       332749823 : js_memcpy(void *dst_, const void *src_, size_t len)
          56                 : {
          57       332749823 :     char *dst = (char *) dst_;
          58       332749823 :     const char *src = (const char *) src_;
          59       332749823 :     JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
          60       332749823 :     JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
          61                 :
          62       332749823 :     return memcpy(dst, src, len);
          63                 : }
          64                 :
          65                 : #ifdef __cplusplus
          66                 : namespace js {
          67                 :
          68                 : template <class T>
          69                 : struct AlignmentTestStruct
          70                 : {
          71                 :     char c;
          72                 :     T t;
          73                 : };
          74                 :
          75                 : /* This macro determines the alignment requirements of a type. */
          76                 : #define JS_ALIGNMENT_OF(t_) \
          77                 :   (sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_))
          78                 :
          79                 : template <class T>
          80                 : class AlignedPtrAndFlag
          81                 : {
          82                 :     uintptr_t bits;
          83                 :
          84                 :   public:
          85                 :     AlignedPtrAndFlag(T *t, bool flag) {
          86                 :         JS_ASSERT((uintptr_t(t) & 1) == 0);
          87                 :         bits = uintptr_t(t) | uintptr_t(flag);
          88                 :     }
          89                 :
          90                 :     T *ptr() const {
          91                 :         return (T *)(bits & ~uintptr_t(1));
          92                 :     }
          93                 :
          94                 :     bool flag() const {
          95                 :         return (bits & 1) != 0;
          96                 :     }
          97                 :
          98                 :     void setPtr(T *t) {
          99                 :         JS_ASSERT((uintptr_t(t) & 1) == 0);
         100                 :         bits = uintptr_t(t) | uintptr_t(flag());
         101                 :     }
         102                 :
         103                 :     void setFlag() {
         104                 :         bits |= 1;
         105                 :     }
         106                 :
         107                 :     void unsetFlag() {
         108                 :         bits &= ~uintptr_t(1);
         109                 :     }
         110                 :
         111                 :     void set(T *t, bool flag) {
         112                 :         JS_ASSERT((uintptr_t(t) & 1) == 0);
         113                 :         bits = uintptr_t(t) | flag;
         114                 :     }
         115                 : };
         116                 :
         117                 : template <class T>
         118                 : static inline void
         119         3276568 : Reverse(T *beg, T *end)
         120                 : {
         121        17304704 :     while (beg != end) {
         122        11640187 :         if (--end == beg)
         123          888619 :             return;
         124        10751568 :         T tmp = *beg;
         125        10751568 :         *beg = *end;
         126        10751568 :         *end = tmp;
         127        10751568 :         ++beg;
         128                 :     }
         129                 : }
         130                 :
         131                 : template <class T>
         132                 : static inline T *
         133              99 : Find(T *beg, T *end, const T &v)
         134                 : {
         135             216 :     for (T *p = beg; p != end; ++p) {
         136             117 :         if (*p == v)
         137               0 :             return p;
         138                 :     }
         139              99 :     return end;
         140                 : }
         141                 :
         142                 : template <class Container>
         143                 : static inline typename Container::ElementType *
         144              99 : Find(Container &c, const typename Container::ElementType &v)
         145                 : {
         146              99 :     return Find(c.begin(), c.end(), v);
         147                 : }
         148                 :
         149                 : template <typename InputIterT, typename CallableT>
         150                 : void
         151                 : ForEach(InputIterT begin, InputIterT end, CallableT f)
         152                 : {
         153                 :     for (; begin != end; ++begin)
         154                 :         f(*begin);
         155                 : }
         156                 :
         157                 : template <class T>
         158                 : static inline T
         159          208058 : Min(T t1, T t2)
         160                 : {
         161          208058 :     return t1 < t2 ? t1 : t2;
         162                 : }
         163                 :
         164                 : template <class T>
         165                 : static inline T
         166       371414024 : Max(T t1, T t2)
         167                 : {
         168       371414024 :     return t1 > t2 ? t1 : t2;
         169                 : }
         170                 :
         171                 : /* Allows a const variable to be initialized after its declaration. */
         172                 : template <class T>
         173                 : static T&
         174                 : InitConst(const T &t)
         175                 : {
         176                 :     return const_cast<T &>(t);
         177                 : }
         178                 :
         179                 : template <class T, class U>
         180                 : JS_ALWAYS_INLINE T &
         181         2174488 : ImplicitCast(U &u)
         182                 : {
         183         2174488 :     T &t = u;
         184         2174488 :     return t;
         185                 : }
         186                 :
         187                 : template<typename T>
         188                 : class AutoScopedAssign
         189                 : {
         190                 :   private:
         191                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
         192                 :     T *addr;
         193                 :     T old;
         194                 :
         195                 :   public:
         196           10915 :     AutoScopedAssign(T *addr, const T &value JS_GUARD_OBJECT_NOTIFIER_PARAM)
         197           10915 :         : addr(addr), old(*addr)
         198                 :     {
         199           10915 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
         200           10915 :         *addr = value;
         201           10915 :     }
         202                 :
         203           10915 :     ~AutoScopedAssign() { *addr = old; }
         204                 : };
         205                 :
         206                 : template <class T>
         207                 : JS_ALWAYS_INLINE static void
         208        29359066 : PodZero(T *t)
         209                 : {
         210        29359066 :     memset(t, 0, sizeof(T));
         211        29359066 : }
         212                 :
         213                 : template <class T>
         214                 : JS_ALWAYS_INLINE static void
         215         7592618 : PodZero(T *t, size_t nelem)
         216                 : {
         217                 :     /*
         218                 :      * This function is often called with 'nelem' small; we use an
         219                 :      * inline loop instead of calling 'memset' with a non-constant
         220                 :      * length.  The compiler should inline the memset call with constant
         221                 :      * size, though.
         222                 :      */
         223        49519544 :     for (T *end = t + nelem; t != end; ++t)
         224        41926926 :         memset(t, 0, sizeof(T));
         225         7592618 : }
         226                 :
         227                 : /*
         228                 :  * Arrays implicitly convert to pointers to their first element, which is
         229                 :  * dangerous when combined with the above PodZero definitions. Adding an
         230                 :  * overload for arrays is ambiguous, so we need another identifier. The
         231                 :  * ambiguous overload is left to catch mistaken uses of PodZero; if you get a
         232                 :  * compile error involving PodZero and array types, use PodArrayZero instead.
         233                 :  */
         234                 : template <class T, size_t N> static void PodZero(T (&)[N]);          /* undefined */
         235                 : template <class T, size_t N> static void PodZero(T (&)[N], size_t);  /* undefined */
         236                 :
         237                 : template <class T, size_t N>
         238                 : JS_ALWAYS_INLINE static void
         239         1202998 : PodArrayZero(T (&t)[N])
         240                 : {
         241         1202998 :     memset(t, 0, N * sizeof(T));
         242         1202998 : }
         243                 :
         244                 : template <class T>
         245                 : JS_ALWAYS_INLINE static void
         246       310338513 : PodAssign(T *dst, const T *src)
         247                 : {
         248       310338513 :     js_memcpy((char *) dst, (const char *) src, sizeof(T));
         249       310338513 : }
         250                 :
         251                 : template <class T>
         252                 : JS_ALWAYS_INLINE static void
         253       107062545 : PodCopy(T *dst, const T *src, size_t nelem)
         254                 : {
         255                 :     /* Cannot find portable word-sized abs(). */
         256       107062545 :     JS_ASSERT_IF(dst >= src, size_t(dst - src) >= nelem);
         257       107062545 :     JS_ASSERT_IF(src >= dst, size_t(src - dst) >= nelem);
         258                 :
         259       107062545 :     if (nelem < 128) {
         260                 :         /*
         261                 :          * Avoid using operator= in this loop, as it may have been
         262                 :          * intentionally deleted by the POD type.
         263                 :          */
         264       417345166 :         for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
         265       310335903 :             PodAssign(dst, src);
         266                 :     } else {
         267           53282 :         memcpy(dst, src, nelem * sizeof(T));
         268                 :     }
         269       107062545 : }
         270                 :
         271                 : template <class T>
         272                 : JS_ALWAYS_INLINE static bool
         273        20959946 : PodEqual(T *one, T *two, size_t len)
         274                 : {
         275        20959946 :     if (len < 128) {
         276        20908280 :         T *p1end = one + len;
         277       163309462 :         for (T *p1 = one, *p2 = two; p1 != p1end; ++p1, ++p2) {
         278       143129865 :             if (*p1 != *p2)
         279          728683 :                 return false;
         280                 :         }
         281        20179597 :         return true;
         282                 :     }
         283                 :
         284           51666 :     return !memcmp(one, two, len * sizeof(T));
         285                 : }
         286                 :
         287                 : template <class T>
         288                 : JS_ALWAYS_INLINE static void
         289            2241 : Swap(T &t, T &u)
         290                 : {
         291            2241 :     T tmp(Move(t));
         292            2241 :     t = Move(u);
         293            2241 :     u = Move(tmp);
         294            2241 : }
         295                 :
         296                 : JS_ALWAYS_INLINE static size_t
         297             270 : UnsignedPtrDiff(const void *bigger, const void *smaller)
         298                 : {
         299             270 :     return size_t(bigger) - size_t(smaller);
         300                 : }
         301                 :
         302                 : /*
         303                 :  * Ordinarily, a function taking a JSContext* 'cx' parameter reports errors on
         304                 :  * the context. In some cases, functions optionally report and indicate this by
         305                 :  * taking a nullable 'maybecx' parameter. In some cases, though, a function
         306                 :  * always needs a 'cx', but optionally reports. This option is presented by the
         307                 :  * MaybeReportError.
         308                 :  */
         309                 : enum MaybeReportError { REPORT_ERROR = true, DONT_REPORT_ERROR = false };
         310                 :
         311                 : /*****************************************************************************/
         312                 :
         313                 : /* A bit array is an array of bits represented by an array of words (size_t). */
         314                 :
         315                 : static inline unsigned
         316          575637 : NumWordsForBitArrayOfLength(size_t length)
         317                 : {
         318          575637 :     return (length + (JS_BITS_PER_WORD - 1)) / JS_BITS_PER_WORD;
         319                 : }
         320                 :
         321                 : static inline unsigned
         322         1292732 : BitArrayIndexToWordIndex(size_t length, size_t bitIndex)
         323                 : {
         324         1292732 :     unsigned wordIndex = bitIndex / JS_BITS_PER_WORD;
         325         1292732 :     JS_ASSERT(wordIndex < length);
         326         1292732 :     return wordIndex;
         327                 : }
         328                 :
         329                 : static inline size_t
         330         1292732 : BitArrayIndexToWordMask(size_t i)
         331                 : {
         332         1292732 :     return size_t(1) << (i % JS_BITS_PER_WORD);
         333                 : }
         334                 :
         335                 : static inline bool
         336         1292318 : IsBitArrayElementSet(size_t *array, size_t length, size_t i)
         337                 : {
         338         1292318 :     return array[BitArrayIndexToWordIndex(length, i)] & BitArrayIndexToWordMask(i);
         339                 : }
         340                 :
         341                 : static inline bool
         342          213197 : IsAnyBitArrayElementSet(size_t *array, size_t length)
         343                 : {
         344          213197 :     unsigned numWords = NumWordsForBitArrayOfLength(length);
         345          398633 :     for (unsigned i = 0; i < numWords; ++i) {
         346          185481 :         if (array[i])
         347              45 :             return true;
         348                 :     }
         349          213152 :     return false;
         350                 : }
         351                 :
         352                 : static inline void
         353             414 : SetBitArrayElement(size_t *array, size_t length, size_t i)
         354                 : {
         355             414 :     array[BitArrayIndexToWordIndex(length, i)] |= BitArrayIndexToWordMask(i);
         356             414 : }
         357                 :
         358                 : static inline void
         359                 : ClearBitArrayElement(size_t *array, size_t length, size_t i)
         360                 : {
         361                 :     array[BitArrayIndexToWordIndex(length, i)] &= ~BitArrayIndexToWordMask(i);
         362                 : }
         363                 :
         364                 : static inline void
         365          362440 : ClearAllBitArrayElements(size_t *array, size_t length)
         366                 : {
         367          693061 :     for (unsigned i = 0; i < length; ++i)
         368          330621 :         array[i] = 0;
         369          362440 : }
         370                 :
         371                 : }  /* namespace js */
         372                 : #endif  /* __cplusplus */
         373                 :
         374                 : /*
         375                 :  * JS_ROTATE_LEFT32
         376                 :  *
         377                 :  * There is no rotate operation in the C Language so the construct (a << 4) |
         378                 :  * (a >> 28) is used instead. Most compilers convert this to a rotate
         379                 :  * instruction but some versions of MSVC don't without a little help.  To get
         380                 :  * MSVC to generate a rotate instruction, we have to use the _rotl intrinsic
         381                 :  * and use a pragma to make _rotl inline.
         382                 :  *
         383                 :  * MSVC in VS2005 will do an inline rotate instruction on the above construct.
         384                 :  */
         385                 : #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
         386                 :     defined(_M_X64))
         387                 : #include <stdlib.h>
         388                 : #pragma intrinsic(_rotl)
         389                 : #define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
         390                 : #else
         391                 : #define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
         392                 : #endif
         393                 :
         394                 : /* Static control-flow checks. */
         395                 : #ifdef NS_STATIC_CHECKING
         396                 : /* Trigger a control flow check to make sure that code flows through label */
         397                 : inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
         398                 :
         399                 : /* Avoid unused goto-label warnings. */
         400                 : # define MUST_FLOW_LABEL(label) goto label; label:
         401                 :
         402                 : #else
         403                 : # define MUST_FLOW_THROUGH(label)            ((void) 0)
         404                 : # define MUST_FLOW_LABEL(label)
         405                 : #endif
         406                 :
         407                 : /* Crash diagnostics */
         408                 : #ifdef DEBUG
         409                 : # define JS_CRASH_DIAGNOSTICS 1
         410                 : #endif
         411                 : #ifdef JS_CRASH_DIAGNOSTICS
         412                 : # define JS_POISON(p, val, size) memset((p), (val), (size))
         413                 : # define JS_OPT_ASSERT(expr)                                                  \
         414                 :     ((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
         415                 : # define JS_OPT_ASSERT_IF(cond, expr)                                         \
         416                 :     ((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
         417                 : #else
         418                 : # define JS_POISON(p, val, size) ((void) 0)
         419                 : # define JS_OPT_ASSERT(expr) ((void) 0)
         420                 : # define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
         421                 : #endif
         422                 :
         423                 : /* Basic stats */
         424                 : #ifdef DEBUG
         425                 : # define JS_BASIC_STATS 1
         426                 : #endif
         427                 : #ifdef JS_BASIC_STATS
         428                 : # include <stdio.h>
         429                 : typedef struct JSBasicStats {
         430                 :     uint32_t    num;
         431                 :     uint32_t    max;
         432                 :     double      sum;
         433                 :     double      sqsum;
         434                 :     uint32_t    logscale;           /* logarithmic scale: 0 (linear), 2, 10 */
         435                 :     uint32_t    hist[11];
         436                 : } JSBasicStats;
         437                 : # define JS_INIT_STATIC_BASIC_STATS  {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
         438                 : # define JS_BASIC_STATS_INIT(bs)     memset((bs), 0, sizeof(JSBasicStats))
         439                 : # define JS_BASIC_STATS_ACCUM(bs,val)                                         \
         440                 :     JS_BasicStatsAccum(bs, val)
         441                 : # define JS_MeanAndStdDevBS(bs,sigma)                                         \
         442                 :     JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
         443                 : extern void
         444                 : JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val);
         445                 : extern double
         446                 : JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma);
         447                 : extern void
         448                 : JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
         449                 : extern void
         450                 : JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
         451                 : #else
         452                 : # define JS_BASIC_STATS_ACCUM(bs,val)
         453                 : #endif
         454                 :
         455                 : /* A jsbitmap_t is a long integer that can be used for bitmaps. */
         456                 : typedef size_t jsbitmap;
         457                 : #define JS_TEST_BIT(_map,_bit)  ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &      \
         458                 :                                  ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
         459                 : #define JS_SET_BIT(_map,_bit)   ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |=     \
         460                 :                                  ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
         461                 : #define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &=     \
         462                 :                                  ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
         463                 :
         464                 : /* Wrapper for various macros to stop warnings coming from their expansions. */
         465                 : #if defined(__clang__)
         466                 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr)                                \
         467                 :     JS_BEGIN_MACRO                                                            \
         468                 :         _Pragma("clang diagnostic push")                                      \
         469                 :         _Pragma("clang diagnostic ignored \"-Wunused-value\"")                \
         470                 :         expr;                                                                 \
         471                 :         _Pragma("clang diagnostic pop")                                       \
         472                 :     JS_END_MACRO
         473                 : #elif (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
         474                 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr)                                \
         475                 :     JS_BEGIN_MACRO                                                            \
         476                 :         _Pragma("GCC diagnostic push")                                        \
         477                 :         _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"")       \
         478                 :         expr;                                                                 \
         479                 :         _Pragma("GCC diagnostic pop")                                         \
         480                 :     JS_END_MACRO
         481                 : #else
         482                 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr)                                \
         483                 :     JS_BEGIN_MACRO                                                            \
         484                 :         expr;                                                                 \
         485                 :     JS_END_MACRO
         486                 : #endif
         487                 :
         488                 : #endif /* jsutil_h___ */

Generated by: LCOV version 1.7