js/src/jsutil.h

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

mercurial