js/src/jsutil.h

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /*
michael@0 8 * PR assertion checker.
michael@0 9 */
michael@0 10
michael@0 11 #ifndef jsutil_h
michael@0 12 #define jsutil_h
michael@0 13
michael@0 14 #include "mozilla/Assertions.h"
michael@0 15 #include "mozilla/Compiler.h"
michael@0 16 #include "mozilla/GuardObjects.h"
michael@0 17
michael@0 18 #include <limits.h>
michael@0 19
michael@0 20 #include "js/Utility.h"
michael@0 21
michael@0 22 #define JS_ALWAYS_TRUE(expr) MOZ_ALWAYS_TRUE(expr)
michael@0 23 #define JS_ALWAYS_FALSE(expr) MOZ_ALWAYS_FALSE(expr)
michael@0 24
michael@0 25 #if defined(JS_DEBUG)
michael@0 26 # define JS_DIAGNOSTICS_ASSERT(expr) MOZ_ASSERT(expr)
michael@0 27 #elif defined(JS_CRASH_DIAGNOSTICS)
michael@0 28 # define JS_DIAGNOSTICS_ASSERT(expr) do { if (MOZ_UNLIKELY(!(expr))) MOZ_CRASH(); } while(0)
michael@0 29 #else
michael@0 30 # define JS_DIAGNOSTICS_ASSERT(expr) ((void) 0)
michael@0 31 #endif
michael@0 32
michael@0 33 static MOZ_ALWAYS_INLINE void *
michael@0 34 js_memcpy(void *dst_, const void *src_, size_t len)
michael@0 35 {
michael@0 36 char *dst = (char *) dst_;
michael@0 37 const char *src = (const char *) src_;
michael@0 38 JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
michael@0 39 JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
michael@0 40
michael@0 41 return memcpy(dst, src, len);
michael@0 42 }
michael@0 43
michael@0 44 namespace js {
michael@0 45
michael@0 46 template <class T>
michael@0 47 struct AlignmentTestStruct
michael@0 48 {
michael@0 49 char c;
michael@0 50 T t;
michael@0 51 };
michael@0 52
michael@0 53 /* This macro determines the alignment requirements of a type. */
michael@0 54 #define JS_ALIGNMENT_OF(t_) \
michael@0 55 (sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_))
michael@0 56
michael@0 57 template <class T>
michael@0 58 class AlignedPtrAndFlag
michael@0 59 {
michael@0 60 uintptr_t bits;
michael@0 61
michael@0 62 public:
michael@0 63 AlignedPtrAndFlag(T *t, bool aFlag) {
michael@0 64 JS_ASSERT((uintptr_t(t) & 1) == 0);
michael@0 65 bits = uintptr_t(t) | uintptr_t(aFlag);
michael@0 66 }
michael@0 67
michael@0 68 T *ptr() const {
michael@0 69 return (T *)(bits & ~uintptr_t(1));
michael@0 70 }
michael@0 71
michael@0 72 bool flag() const {
michael@0 73 return (bits & 1) != 0;
michael@0 74 }
michael@0 75
michael@0 76 void setPtr(T *t) {
michael@0 77 JS_ASSERT((uintptr_t(t) & 1) == 0);
michael@0 78 bits = uintptr_t(t) | uintptr_t(flag());
michael@0 79 }
michael@0 80
michael@0 81 void setFlag() {
michael@0 82 bits |= 1;
michael@0 83 }
michael@0 84
michael@0 85 void unsetFlag() {
michael@0 86 bits &= ~uintptr_t(1);
michael@0 87 }
michael@0 88
michael@0 89 void set(T *t, bool aFlag) {
michael@0 90 JS_ASSERT((uintptr_t(t) & 1) == 0);
michael@0 91 bits = uintptr_t(t) | aFlag;
michael@0 92 }
michael@0 93 };
michael@0 94
michael@0 95 template <class T>
michael@0 96 static inline void
michael@0 97 Reverse(T *beg, T *end)
michael@0 98 {
michael@0 99 while (beg != end) {
michael@0 100 if (--end == beg)
michael@0 101 return;
michael@0 102 T tmp = *beg;
michael@0 103 *beg = *end;
michael@0 104 *end = tmp;
michael@0 105 ++beg;
michael@0 106 }
michael@0 107 }
michael@0 108
michael@0 109 template <class T>
michael@0 110 static inline T *
michael@0 111 Find(T *beg, T *end, const T &v)
michael@0 112 {
michael@0 113 for (T *p = beg; p != end; ++p) {
michael@0 114 if (*p == v)
michael@0 115 return p;
michael@0 116 }
michael@0 117 return end;
michael@0 118 }
michael@0 119
michael@0 120 template <class Container>
michael@0 121 static inline typename Container::ElementType *
michael@0 122 Find(Container &c, const typename Container::ElementType &v)
michael@0 123 {
michael@0 124 return Find(c.begin(), c.end(), v);
michael@0 125 }
michael@0 126
michael@0 127 template <typename InputIterT, typename CallableT>
michael@0 128 void
michael@0 129 ForEach(InputIterT begin, InputIterT end, CallableT f)
michael@0 130 {
michael@0 131 for (; begin != end; ++begin)
michael@0 132 f(*begin);
michael@0 133 }
michael@0 134
michael@0 135 template <class T>
michael@0 136 static inline T
michael@0 137 Min(T t1, T t2)
michael@0 138 {
michael@0 139 return t1 < t2 ? t1 : t2;
michael@0 140 }
michael@0 141
michael@0 142 template <class T>
michael@0 143 static inline T
michael@0 144 Max(T t1, T t2)
michael@0 145 {
michael@0 146 return t1 > t2 ? t1 : t2;
michael@0 147 }
michael@0 148
michael@0 149 /* Allows a const variable to be initialized after its declaration. */
michael@0 150 template <class T>
michael@0 151 static T&
michael@0 152 InitConst(const T &t)
michael@0 153 {
michael@0 154 return const_cast<T &>(t);
michael@0 155 }
michael@0 156
michael@0 157 template <class T, class U>
michael@0 158 MOZ_ALWAYS_INLINE T &
michael@0 159 ImplicitCast(U &u)
michael@0 160 {
michael@0 161 T &t = u;
michael@0 162 return t;
michael@0 163 }
michael@0 164
michael@0 165 template<typename T>
michael@0 166 class AutoScopedAssign
michael@0 167 {
michael@0 168 public:
michael@0 169 AutoScopedAssign(T *addr, const T &value
michael@0 170 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
michael@0 171 : addr_(addr), old(*addr_)
michael@0 172 {
michael@0 173 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
michael@0 174 *addr_ = value;
michael@0 175 }
michael@0 176
michael@0 177 ~AutoScopedAssign() { *addr_ = old; }
michael@0 178
michael@0 179 private:
michael@0 180 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 181 T *addr_;
michael@0 182 T old;
michael@0 183 };
michael@0 184
michael@0 185 template <typename T>
michael@0 186 static inline bool
michael@0 187 IsPowerOfTwo(T t)
michael@0 188 {
michael@0 189 return t && !(t & (t - 1));
michael@0 190 }
michael@0 191
michael@0 192 template <typename T, typename U>
michael@0 193 static inline U
michael@0 194 ComputeByteAlignment(T bytes, U alignment)
michael@0 195 {
michael@0 196 JS_ASSERT(IsPowerOfTwo(alignment));
michael@0 197 return (alignment - (bytes % alignment)) % alignment;
michael@0 198 }
michael@0 199
michael@0 200 template <typename T, typename U>
michael@0 201 static inline T
michael@0 202 AlignBytes(T bytes, U alignment)
michael@0 203 {
michael@0 204 return bytes + ComputeByteAlignment(bytes, alignment);
michael@0 205 }
michael@0 206
michael@0 207 static MOZ_ALWAYS_INLINE size_t
michael@0 208 UnsignedPtrDiff(const void *bigger, const void *smaller)
michael@0 209 {
michael@0 210 return size_t(bigger) - size_t(smaller);
michael@0 211 }
michael@0 212
michael@0 213 /*****************************************************************************/
michael@0 214
michael@0 215 /* A bit array is an array of bits represented by an array of words (size_t). */
michael@0 216
michael@0 217 static const size_t BitArrayElementBits = sizeof(size_t) * CHAR_BIT;
michael@0 218
michael@0 219 static inline unsigned
michael@0 220 NumWordsForBitArrayOfLength(size_t length)
michael@0 221 {
michael@0 222 return (length + (BitArrayElementBits - 1)) / BitArrayElementBits;
michael@0 223 }
michael@0 224
michael@0 225 static inline unsigned
michael@0 226 BitArrayIndexToWordIndex(size_t length, size_t bitIndex)
michael@0 227 {
michael@0 228 unsigned wordIndex = bitIndex / BitArrayElementBits;
michael@0 229 JS_ASSERT(wordIndex < length);
michael@0 230 return wordIndex;
michael@0 231 }
michael@0 232
michael@0 233 static inline size_t
michael@0 234 BitArrayIndexToWordMask(size_t i)
michael@0 235 {
michael@0 236 return size_t(1) << (i % BitArrayElementBits);
michael@0 237 }
michael@0 238
michael@0 239 static inline bool
michael@0 240 IsBitArrayElementSet(size_t *array, size_t length, size_t i)
michael@0 241 {
michael@0 242 return array[BitArrayIndexToWordIndex(length, i)] & BitArrayIndexToWordMask(i);
michael@0 243 }
michael@0 244
michael@0 245 static inline bool
michael@0 246 IsAnyBitArrayElementSet(size_t *array, size_t length)
michael@0 247 {
michael@0 248 unsigned numWords = NumWordsForBitArrayOfLength(length);
michael@0 249 for (unsigned i = 0; i < numWords; ++i) {
michael@0 250 if (array[i])
michael@0 251 return true;
michael@0 252 }
michael@0 253 return false;
michael@0 254 }
michael@0 255
michael@0 256 static inline void
michael@0 257 SetBitArrayElement(size_t *array, size_t length, size_t i)
michael@0 258 {
michael@0 259 array[BitArrayIndexToWordIndex(length, i)] |= BitArrayIndexToWordMask(i);
michael@0 260 }
michael@0 261
michael@0 262 static inline void
michael@0 263 ClearBitArrayElement(size_t *array, size_t length, size_t i)
michael@0 264 {
michael@0 265 array[BitArrayIndexToWordIndex(length, i)] &= ~BitArrayIndexToWordMask(i);
michael@0 266 }
michael@0 267
michael@0 268 static inline void
michael@0 269 ClearAllBitArrayElements(size_t *array, size_t length)
michael@0 270 {
michael@0 271 for (unsigned i = 0; i < length; ++i)
michael@0 272 array[i] = 0;
michael@0 273 }
michael@0 274
michael@0 275 } /* namespace js */
michael@0 276
michael@0 277 /* Crash diagnostics */
michael@0 278 #ifdef DEBUG
michael@0 279 # define JS_CRASH_DIAGNOSTICS 1
michael@0 280 #endif
michael@0 281 #if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL)
michael@0 282 # define JS_POISON(p, val, size) memset((p), (val), (size))
michael@0 283 #else
michael@0 284 # define JS_POISON(p, val, size) ((void) 0)
michael@0 285 #endif
michael@0 286
michael@0 287 /* Bug 984101: Disable labeled poisoning until we have poison checking. */
michael@0 288 #define JS_EXTRA_POISON(p, val, size) ((void) 0)
michael@0 289
michael@0 290 /* Basic stats */
michael@0 291 #ifdef DEBUG
michael@0 292 # define JS_BASIC_STATS 1
michael@0 293 #endif
michael@0 294 #ifdef JS_BASIC_STATS
michael@0 295 # include <stdio.h>
michael@0 296 typedef struct JSBasicStats {
michael@0 297 uint32_t num;
michael@0 298 uint32_t max;
michael@0 299 double sum;
michael@0 300 double sqsum;
michael@0 301 uint32_t logscale; /* logarithmic scale: 0 (linear), 2, 10 */
michael@0 302 uint32_t hist[11];
michael@0 303 } JSBasicStats;
michael@0 304 # define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
michael@0 305 # define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
michael@0 306 # define JS_BASIC_STATS_ACCUM(bs,val) \
michael@0 307 JS_BasicStatsAccum(bs, val)
michael@0 308 # define JS_MeanAndStdDevBS(bs,sigma) \
michael@0 309 JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
michael@0 310 extern void
michael@0 311 JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val);
michael@0 312 extern double
michael@0 313 JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma);
michael@0 314 extern void
michael@0 315 JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
michael@0 316 extern void
michael@0 317 JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
michael@0 318 #else
michael@0 319 # define JS_BASIC_STATS_ACCUM(bs,val)
michael@0 320 #endif
michael@0 321
michael@0 322 /* A jsbitmap_t is a long integer that can be used for bitmaps. */
michael@0 323 typedef size_t jsbitmap;
michael@0 324 #define JS_BITMAP_NBITS (sizeof(jsbitmap) * CHAR_BIT)
michael@0 325 #define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] & \
michael@0 326 (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
michael@0 327 #define JS_SET_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] |= \
michael@0 328 (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
michael@0 329 #define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] &= \
michael@0 330 ~(jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
michael@0 331
michael@0 332 /* Wrapper for various macros to stop warnings coming from their expansions. */
michael@0 333 #if defined(__clang__)
michael@0 334 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
michael@0 335 JS_BEGIN_MACRO \
michael@0 336 _Pragma("clang diagnostic push") \
michael@0 337 /* If these _Pragmas cause warnings for you, try disabling ccache. */ \
michael@0 338 _Pragma("clang diagnostic ignored \"-Wunused-value\"") \
michael@0 339 { expr; } \
michael@0 340 _Pragma("clang diagnostic pop") \
michael@0 341 JS_END_MACRO
michael@0 342 #elif MOZ_IS_GCC
michael@0 343
michael@0 344 #if MOZ_GCC_VERSION_AT_LEAST(4, 6, 0)
michael@0 345 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
michael@0 346 JS_BEGIN_MACRO \
michael@0 347 _Pragma("GCC diagnostic push") \
michael@0 348 _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
michael@0 349 expr; \
michael@0 350 _Pragma("GCC diagnostic pop") \
michael@0 351 JS_END_MACRO
michael@0 352 #endif
michael@0 353 #endif
michael@0 354
michael@0 355 #if !defined(JS_SILENCE_UNUSED_VALUE_IN_EXPR)
michael@0 356 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
michael@0 357 JS_BEGIN_MACRO \
michael@0 358 expr; \
michael@0 359 JS_END_MACRO
michael@0 360 #endif
michael@0 361
michael@0 362 #endif /* jsutil_h */

mercurial