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 674792726 : js_memcpy(void *dst_, const void *src_, size_t len)
56 : {
57 674792726 : char *dst = (char *) dst_;
58 674792726 : const char *src = (const char *) src_;
59 674792726 : JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
60 674792729 : JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
61 :
62 674792729 : return memcpy(dst, src, len);
63 : }
64 :
65 : #ifdef __cplusplus
66 : namespace js {
67 :
68 : template <class T>
69 : class AlignedPtrAndFlag
70 : {
71 : uintptr_t bits;
72 :
73 : public:
74 : AlignedPtrAndFlag(T *t, bool flag) {
75 : JS_ASSERT((uintptr_t(t) & 1) == 0);
76 : bits = uintptr_t(t) | uintptr_t(flag);
77 : }
78 :
79 : T *ptr() const {
80 : return (T *)(bits & ~uintptr_t(1));
81 : }
82 :
83 : bool flag() const {
84 : return (bits & 1) != 0;
85 : }
86 :
87 : void setPtr(T *t) {
88 : JS_ASSERT((uintptr_t(t) & 1) == 0);
89 : bits = uintptr_t(t) | uintptr_t(flag());
90 : }
91 :
92 : void setFlag() {
93 : bits |= 1;
94 : }
95 :
96 : void unsetFlag() {
97 : bits &= ~uintptr_t(1);
98 : }
99 :
100 : void set(T *t, bool flag) {
101 : JS_ASSERT((uintptr_t(t) & 1) == 0);
102 : bits = uintptr_t(t) | flag;
103 : }
104 : };
105 :
106 : template <class T>
107 : static inline void
108 3667886 : Reverse(T *beg, T *end)
109 : {
110 18296445 : while (beg != end) {
111 11918305 : if (--end == beg)
112 957632 : return;
113 10960673 : T tmp = *beg;
114 10960673 : *beg = *end;
115 10960673 : *end = tmp;
116 10960673 : ++beg;
117 : }
118 : }
119 :
120 : template <class T>
121 : static inline T *
122 99 : Find(T *beg, T *end, const T &v)
123 : {
124 216 : for (T *p = beg; p != end; ++p) {
125 117 : if (*p == v)
126 0 : return p;
127 : }
128 99 : return end;
129 : }
130 :
131 : template <class Container>
132 : static inline typename Container::ElementType *
133 99 : Find(Container &c, const typename Container::ElementType &v)
134 : {
135 99 : return Find(c.begin(), c.end(), v);
136 : }
137 :
138 : template <typename InputIterT, typename CallableT>
139 : void
140 : ForEach(InputIterT begin, InputIterT end, CallableT f)
141 : {
142 : for (; begin != end; ++begin)
143 : f(*begin);
144 : }
145 :
146 : template <class T>
147 : static inline T
148 288727 : Min(T t1, T t2)
149 : {
150 288727 : return t1 < t2 ? t1 : t2;
151 : }
152 :
153 : template <class T>
154 : static inline T
155 604352700 : Max(T t1, T t2)
156 : {
157 604352700 : return t1 > t2 ? t1 : t2;
158 : }
159 :
160 : /* Allows a const variable to be initialized after its declaration. */
161 : template <class T>
162 : static T&
163 : InitConst(const T &t)
164 : {
165 : return const_cast<T &>(t);
166 : }
167 :
168 : template <class T, class U>
169 : JS_ALWAYS_INLINE T &
170 6140114 : ImplicitCast(U &u)
171 : {
172 6140114 : T &t = u;
173 6140114 : return t;
174 : }
175 :
176 : template<typename T>
177 : class AutoScopedAssign
178 : {
179 : private:
180 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
181 : T *addr;
182 : T old;
183 :
184 : public:
185 : AutoScopedAssign(T *addr, const T &value JS_GUARD_OBJECT_NOTIFIER_PARAM)
186 : : addr(addr), old(*addr)
187 : {
188 : JS_GUARD_OBJECT_NOTIFIER_INIT;
189 : *addr = value;
190 : }
191 :
192 : ~AutoScopedAssign() { *addr = old; }
193 : };
194 :
195 : template <class T>
196 : JS_ALWAYS_INLINE static void
197 173905362 : PodZero(T *t)
198 : {
199 173905362 : memset(t, 0, sizeof(T));
200 173905362 : }
201 :
202 : template <class T>
203 : JS_ALWAYS_INLINE static void
204 13087199 : PodZero(T *t, size_t nelem)
205 : {
206 : /*
207 : * This function is often called with 'nelem' small; we use an
208 : * inline loop instead of calling 'memset' with a non-constant
209 : * length. The compiler should inline the memset call with constant
210 : * size, though.
211 : */
212 380636648 : for (T *end = t + nelem; t != end; ++t)
213 367549449 : memset(t, 0, sizeof(T));
214 13087199 : }
215 :
216 : /*
217 : * Arrays implicitly convert to pointers to their first element, which is
218 : * dangerous when combined with the above PodZero definitions. Adding an
219 : * overload for arrays is ambiguous, so we need another identifier. The
220 : * ambiguous overload is left to catch mistaken uses of PodZero; if you get a
221 : * compile error involving PodZero and array types, use PodArrayZero instead.
222 : */
223 : template <class T, size_t N> static void PodZero(T (&)[N]); /* undefined */
224 : template <class T, size_t N> static void PodZero(T (&)[N], size_t); /* undefined */
225 :
226 : template <class T, size_t N>
227 : JS_ALWAYS_INLINE static void
228 1642607 : PodArrayZero(T (&t)[N])
229 : {
230 1642607 : memset(t, 0, N * sizeof(T));
231 1642607 : }
232 :
233 : template <class T>
234 : JS_ALWAYS_INLINE static void
235 636460102 : PodAssign(T *dst, const T *src)
236 : {
237 636460102 : js_memcpy((char *) dst, (const char *) src, sizeof(T));
238 636460101 : }
239 :
240 : template <class T>
241 : JS_ALWAYS_INLINE static void
242 134155726 : PodCopy(T *dst, const T *src, size_t nelem)
243 : {
244 : /* Cannot find portable word-sized abs(). */
245 134155726 : JS_ASSERT_IF(dst >= src, size_t(dst - src) >= nelem);
246 134155727 : JS_ASSERT_IF(src >= dst, size_t(src - dst) >= nelem);
247 :
248 134155727 : if (nelem < 128) {
249 : /*
250 : * Avoid using operator= in this loop, as it may have been
251 : * intentionally deleted by the POD type.
252 : */
253 768751746 : for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
254 636452594 : PodAssign(dst, src);
255 : } else {
256 1856572 : memcpy(dst, src, nelem * sizeof(T));
257 : }
258 134155724 : }
259 :
260 : template <class T>
261 : JS_ALWAYS_INLINE static bool
262 56184005 : PodEqual(T *one, T *two, size_t len)
263 : {
264 56184005 : if (len < 128) {
265 55999684 : T *p1end = one + len;
266 644003216 : for (T *p1 = one, *p2 = two; p1 != p1end; ++p1, ++p2) {
267 590118312 : if (*p1 != *p2)
268 2114780 : return false;
269 : }
270 53884904 : return true;
271 : }
272 :
273 184321 : return !memcmp(one, two, len * sizeof(T));
274 : }
275 :
276 : JS_ALWAYS_INLINE static size_t
277 270 : UnsignedPtrDiff(const void *bigger, const void *smaller)
278 : {
279 270 : return size_t(bigger) - size_t(smaller);
280 : }
281 :
282 : /*
283 : * Ordinarily, a function taking a JSContext* 'cx' parameter reports errors on
284 : * the context. In some cases, functions optionally report and indicate this by
285 : * taking a nullable 'maybecx' parameter. In some cases, though, a function
286 : * always needs a 'cx', but optionally reports. This option is presented by the
287 : * MaybeReportError.
288 : */
289 : enum MaybeReportError { REPORT_ERROR = true, DONT_REPORT_ERROR = false };
290 :
291 : } /* namespace js */
292 : #endif /* __cplusplus */
293 :
294 : /*
295 : * JS_ROTATE_LEFT32
296 : *
297 : * There is no rotate operation in the C Language so the construct (a << 4) |
298 : * (a >> 28) is used instead. Most compilers convert this to a rotate
299 : * instruction but some versions of MSVC don't without a little help. To get
300 : * MSVC to generate a rotate instruction, we have to use the _rotl intrinsic
301 : * and use a pragma to make _rotl inline.
302 : *
303 : * MSVC in VS2005 will do an inline rotate instruction on the above construct.
304 : */
305 : #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
306 : defined(_M_X64))
307 : #include <stdlib.h>
308 : #pragma intrinsic(_rotl)
309 : #define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
310 : #else
311 : #define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
312 : #endif
313 :
314 : /* Static control-flow checks. */
315 : #ifdef NS_STATIC_CHECKING
316 : /* Trigger a control flow check to make sure that code flows through label */
317 : inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
318 :
319 : /* Avoid unused goto-label warnings. */
320 : # define MUST_FLOW_LABEL(label) goto label; label:
321 :
322 : #else
323 : # define MUST_FLOW_THROUGH(label) ((void) 0)
324 : # define MUST_FLOW_LABEL(label)
325 : #endif
326 :
327 : /* Crash diagnostics */
328 : #ifdef DEBUG
329 : # define JS_CRASH_DIAGNOSTICS 1
330 : #endif
331 : #ifdef JS_CRASH_DIAGNOSTICS
332 : # define JS_POISON(p, val, size) memset((p), (val), (size))
333 : # define JS_OPT_ASSERT(expr) \
334 : ((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
335 : # define JS_OPT_ASSERT_IF(cond, expr) \
336 : ((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
337 : #else
338 : # define JS_POISON(p, val, size) ((void) 0)
339 : # define JS_OPT_ASSERT(expr) ((void) 0)
340 : # define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
341 : #endif
342 :
343 : /* Basic stats */
344 : #ifdef DEBUG
345 : # define JS_BASIC_STATS 1
346 : #endif
347 : #ifdef JS_BASIC_STATS
348 : # include <stdio.h>
349 : typedef struct JSBasicStats {
350 : uint32_t num;
351 : uint32_t max;
352 : double sum;
353 : double sqsum;
354 : uint32_t logscale; /* logarithmic scale: 0 (linear), 2, 10 */
355 : uint32_t hist[11];
356 : } JSBasicStats;
357 : # define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
358 : # define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
359 : # define JS_BASIC_STATS_ACCUM(bs,val) \
360 : JS_BasicStatsAccum(bs, val)
361 : # define JS_MeanAndStdDevBS(bs,sigma) \
362 : JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
363 : extern void
364 : JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val);
365 : extern double
366 : JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma);
367 : extern void
368 : JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
369 : extern void
370 : JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
371 : #else
372 : # define JS_BASIC_STATS_ACCUM(bs,val)
373 : #endif
374 :
375 : /* A jsbitmap_t is a long integer that can be used for bitmaps. */
376 : typedef size_t jsbitmap;
377 : #define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & \
378 : ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
379 : #define JS_SET_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= \
380 : ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
381 : #define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= \
382 : ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
383 :
384 : /* Wrapper for various macros to stop warnings coming from their expansions. */
385 : #if defined(__clang__)
386 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
387 : JS_BEGIN_MACRO \
388 : _Pragma("clang diagnostic push") \
389 : _Pragma("clang diagnostic ignored \"-Wunused-value\"") \
390 : expr; \
391 : _Pragma("clang diagnostic pop") \
392 : JS_END_MACRO
393 : #elif (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
394 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
395 : JS_BEGIN_MACRO \
396 : _Pragma("GCC diagnostic push") \
397 : _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
398 : expr; \
399 : _Pragma("GCC diagnostic pop") \
400 : JS_END_MACRO
401 : #else
402 : # define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
403 : JS_BEGIN_MACRO \
404 : expr; \
405 : JS_END_MACRO
406 : #endif
407 :
408 : #endif /* jsutil_h___ */
|