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___ */
|