Bumping manifests a=b2g-bump
[gecko.git] / js / src / jsutil.h
blob5b5231cd26724b4ee3c0ef365234fe01e68c9e9c
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/. */
7 /*
8 * PR assertion checker.
9 */
11 #ifndef jsutil_h
12 #define jsutil_h
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Compiler.h"
16 #include "mozilla/GuardObjects.h"
18 #include <limits.h>
20 #include "js/Utility.h"
22 #define JS_ALWAYS_TRUE(expr) MOZ_ALWAYS_TRUE(expr)
23 #define JS_ALWAYS_FALSE(expr) MOZ_ALWAYS_FALSE(expr)
25 #if defined(JS_DEBUG)
26 # define JS_DIAGNOSTICS_ASSERT(expr) MOZ_ASSERT(expr)
27 #elif defined(JS_CRASH_DIAGNOSTICS)
28 # define JS_DIAGNOSTICS_ASSERT(expr) do { if (MOZ_UNLIKELY(!(expr))) MOZ_CRASH(); } while(0)
29 #else
30 # define JS_DIAGNOSTICS_ASSERT(expr) ((void) 0)
31 #endif
33 static MOZ_ALWAYS_INLINE void *
34 js_memcpy(void *dst_, const void *src_, size_t len)
36 char *dst = (char *) dst_;
37 const char *src = (const char *) src_;
38 JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
39 JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
41 return memcpy(dst, src, len);
44 namespace js {
46 template <class T>
47 struct AlignmentTestStruct
49 char c;
50 T t;
53 /* This macro determines the alignment requirements of a type. */
54 #define JS_ALIGNMENT_OF(t_) \
55 (sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_))
57 template <class T>
58 class AlignedPtrAndFlag
60 uintptr_t bits;
62 public:
63 AlignedPtrAndFlag(T *t, bool aFlag) {
64 JS_ASSERT((uintptr_t(t) & 1) == 0);
65 bits = uintptr_t(t) | uintptr_t(aFlag);
68 T *ptr() const {
69 return (T *)(bits & ~uintptr_t(1));
72 bool flag() const {
73 return (bits & 1) != 0;
76 void setPtr(T *t) {
77 JS_ASSERT((uintptr_t(t) & 1) == 0);
78 bits = uintptr_t(t) | uintptr_t(flag());
81 void setFlag() {
82 bits |= 1;
85 void unsetFlag() {
86 bits &= ~uintptr_t(1);
89 void set(T *t, bool aFlag) {
90 JS_ASSERT((uintptr_t(t) & 1) == 0);
91 bits = uintptr_t(t) | aFlag;
95 template <class T>
96 static inline void
97 Reverse(T *beg, T *end)
99 while (beg != end) {
100 if (--end == beg)
101 return;
102 T tmp = *beg;
103 *beg = *end;
104 *end = tmp;
105 ++beg;
109 template <class T>
110 static inline T *
111 Find(T *beg, T *end, const T &v)
113 for (T *p = beg; p != end; ++p) {
114 if (*p == v)
115 return p;
117 return end;
120 template <class Container>
121 static inline typename Container::ElementType *
122 Find(Container &c, const typename Container::ElementType &v)
124 return Find(c.begin(), c.end(), v);
127 template <typename InputIterT, typename CallableT>
128 void
129 ForEach(InputIterT begin, InputIterT end, CallableT f)
131 for (; begin != end; ++begin)
132 f(*begin);
135 template <class T>
136 static inline T
137 Min(T t1, T t2)
139 return t1 < t2 ? t1 : t2;
142 template <class T>
143 static inline T
144 Max(T t1, T t2)
146 return t1 > t2 ? t1 : t2;
149 /* Allows a const variable to be initialized after its declaration. */
150 template <class T>
151 static T&
152 InitConst(const T &t)
154 return const_cast<T &>(t);
157 template <class T, class U>
158 MOZ_ALWAYS_INLINE T &
159 ImplicitCast(U &u)
161 T &t = u;
162 return t;
165 template<typename T>
166 class AutoScopedAssign
168 public:
169 AutoScopedAssign(T *addr, const T &value
170 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
171 : addr_(addr), old(*addr_)
173 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
174 *addr_ = value;
177 ~AutoScopedAssign() { *addr_ = old; }
179 private:
180 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
181 T *addr_;
182 T old;
185 template <typename T>
186 static inline bool
187 IsPowerOfTwo(T t)
189 return t && !(t & (t - 1));
192 template <typename T, typename U>
193 static inline U
194 ComputeByteAlignment(T bytes, U alignment)
196 JS_ASSERT(IsPowerOfTwo(alignment));
197 return (alignment - (bytes % alignment)) % alignment;
200 template <typename T, typename U>
201 static inline T
202 AlignBytes(T bytes, U alignment)
204 return bytes + ComputeByteAlignment(bytes, alignment);
207 static MOZ_ALWAYS_INLINE size_t
208 UnsignedPtrDiff(const void *bigger, const void *smaller)
210 return size_t(bigger) - size_t(smaller);
213 /*****************************************************************************/
215 /* A bit array is an array of bits represented by an array of words (size_t). */
217 static const size_t BitArrayElementBits = sizeof(size_t) * CHAR_BIT;
219 static inline unsigned
220 NumWordsForBitArrayOfLength(size_t length)
222 return (length + (BitArrayElementBits - 1)) / BitArrayElementBits;
225 static inline unsigned
226 BitArrayIndexToWordIndex(size_t length, size_t bitIndex)
228 unsigned wordIndex = bitIndex / BitArrayElementBits;
229 JS_ASSERT(wordIndex < length);
230 return wordIndex;
233 static inline size_t
234 BitArrayIndexToWordMask(size_t i)
236 return size_t(1) << (i % BitArrayElementBits);
239 static inline bool
240 IsBitArrayElementSet(size_t *array, size_t length, size_t i)
242 return array[BitArrayIndexToWordIndex(length, i)] & BitArrayIndexToWordMask(i);
245 static inline bool
246 IsAnyBitArrayElementSet(size_t *array, size_t length)
248 unsigned numWords = NumWordsForBitArrayOfLength(length);
249 for (unsigned i = 0; i < numWords; ++i) {
250 if (array[i])
251 return true;
253 return false;
256 static inline void
257 SetBitArrayElement(size_t *array, size_t length, size_t i)
259 array[BitArrayIndexToWordIndex(length, i)] |= BitArrayIndexToWordMask(i);
262 static inline void
263 ClearBitArrayElement(size_t *array, size_t length, size_t i)
265 array[BitArrayIndexToWordIndex(length, i)] &= ~BitArrayIndexToWordMask(i);
268 static inline void
269 ClearAllBitArrayElements(size_t *array, size_t length)
271 for (unsigned i = 0; i < length; ++i)
272 array[i] = 0;
275 } /* namespace js */
277 static inline void *
278 Poison(void *ptr, int value, size_t num)
280 static bool inited = false;
281 static bool poison = true;
282 if (!inited) {
283 char *env = getenv("JSGC_DISABLE_POISONING");
284 if (env)
285 poison = false;
286 inited = true;
289 if (poison)
290 return memset(ptr, value, num);
292 return nullptr;
295 /* Crash diagnostics */
296 #ifdef DEBUG
297 # define JS_CRASH_DIAGNOSTICS 1
298 #endif
299 #if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL)
300 # define JS_POISON(p, val, size) Poison(p, val, size)
301 #else
302 # define JS_POISON(p, val, size) ((void) 0)
303 #endif
305 /* Bug 984101: Disable labeled poisoning until we have poison checking. */
306 #define JS_EXTRA_POISON(p, val, size) ((void) 0)
308 /* Basic stats */
309 #ifdef DEBUG
310 # define JS_BASIC_STATS 1
311 #endif
312 #ifdef JS_BASIC_STATS
313 # include <stdio.h>
314 typedef struct JSBasicStats {
315 uint32_t num;
316 uint32_t max;
317 double sum;
318 double sqsum;
319 uint32_t logscale; /* logarithmic scale: 0 (linear), 2, 10 */
320 uint32_t hist[11];
321 } JSBasicStats;
322 # define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
323 # define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
324 # define JS_BASIC_STATS_ACCUM(bs,val) \
325 JS_BasicStatsAccum(bs, val)
326 # define JS_MeanAndStdDevBS(bs,sigma) \
327 JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
328 extern void
329 JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val);
330 extern double
331 JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma);
332 extern void
333 JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
334 extern void
335 JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
336 #else
337 # define JS_BASIC_STATS_ACCUM(bs,val)
338 #endif
340 /* A jsbitmap_t is a long integer that can be used for bitmaps. */
341 typedef size_t jsbitmap;
342 #define JS_BITMAP_NBITS (sizeof(jsbitmap) * CHAR_BIT)
343 #define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] & \
344 (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
345 #define JS_SET_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] |= \
346 (jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
347 #define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)/JS_BITMAP_NBITS] &= \
348 ~(jsbitmap(1)<<((_bit)%JS_BITMAP_NBITS)))
350 /* Wrapper for various macros to stop warnings coming from their expansions. */
351 #if defined(__clang__)
352 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
353 JS_BEGIN_MACRO \
354 _Pragma("clang diagnostic push") \
355 /* If these _Pragmas cause warnings for you, try disabling ccache. */ \
356 _Pragma("clang diagnostic ignored \"-Wunused-value\"") \
357 { expr; } \
358 _Pragma("clang diagnostic pop") \
359 JS_END_MACRO
360 #elif MOZ_IS_GCC
362 #if MOZ_GCC_VERSION_AT_LEAST(4, 6, 0)
363 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
364 JS_BEGIN_MACRO \
365 _Pragma("GCC diagnostic push") \
366 _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
367 expr; \
368 _Pragma("GCC diagnostic pop") \
369 JS_END_MACRO
370 #endif
371 #endif
373 #if !defined(JS_SILENCE_UNUSED_VALUE_IN_EXPR)
374 # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
375 JS_BEGIN_MACRO \
376 expr; \
377 JS_END_MACRO
378 #endif
380 #endif /* jsutil_h */