Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsutil.h
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 "jstypes.h"
48 #include <stdlib.h>
49 #include <string.h>
50
51 JS_BEGIN_EXTERN_C
52
53 /*
54  * JS_Assert is present even in release builds, for the benefit of applications
55  * that build DEBUG and link against a non-DEBUG SpiderMonkey library.
56  */
57 extern JS_PUBLIC_API(void)
58 JS_Assert(const char *s, const char *file, JSIntn ln);
59
60 #define JS_CRASH_UNLESS(__cond)                                                 \
61     JS_BEGIN_MACRO                                                              \
62         if (!(__cond)) {                                                        \
63             *(int *)(uintptr_t)0xccadbeef = 0;                                  \
64             ((void(*)())0)(); /* More reliable, but doesn't say CCADBEEF */     \
65         }                                                                       \
66     JS_END_MACRO
67
68 #ifdef DEBUG
69
70 #define JS_ASSERT(expr)                                                       \
71     ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
72
73 #define JS_ASSERT_IF(cond, expr)                                              \
74     ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
75
76 #define JS_NOT_REACHED(reason)                                                \
77     JS_Assert(reason, __FILE__, __LINE__)
78
79 #define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
80
81 #define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
82
83 # ifdef JS_THREADSAFE
84 # define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr) 
85 # else
86 # define JS_THREADSAFE_ASSERT(expr) ((void) 0)
87 # endif
88
89 #else
90
91 #define JS_ASSERT(expr)         ((void) 0)
92 #define JS_ASSERT_IF(cond,expr) ((void) 0)
93 #define JS_NOT_REACHED(reason)
94 #define JS_ALWAYS_TRUE(expr)    ((void) (expr))
95 #define JS_ALWAYS_FALSE(expr)    ((void) (expr))
96 #define JS_THREADSAFE_ASSERT(expr) ((void) 0)
97
98 #endif /* defined(DEBUG) */
99
100 /*
101  * Compile-time assert. "cond" must be a constant expression.
102  * The macro can be used only in places where an "extern" declaration is
103  * allowed.
104  */
105
106 #ifdef __SUNPRO_CC
107 /*
108  * Sun Studio C++ compiler has a bug
109  * "sizeof expression not accepted as size of array parameter"
110  * It happens when js_static_assert() function is declared inside functions.
111  * The bug number is 6688515. It is not public yet.
112  * Therefore, for Sun Studio, declare js_static_assert as an array instead.
113  */
114 #define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
115 #else
116 #ifdef __COUNTER__
117     #define JS_STATIC_ASSERT_GLUE1(x,y) x##y
118     #define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
119     #define JS_STATIC_ASSERT(cond)                                            \
120         typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
121 #else
122     #define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
123 #endif
124 #endif
125
126 #define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
127
128 /*
129  * Abort the process in a non-graceful manner. This will cause a core file,
130  * call to the debugger or other moral equivalent as well as causing the
131  * entire process to stop.
132  */
133 extern JS_PUBLIC_API(void) JS_Abort(void);
134
135 #ifdef DEBUG
136 # define JS_BASIC_STATS 1
137 #endif
138
139 #ifdef DEBUG_brendan
140 # define JS_SCOPE_DEPTH_METER 1
141 #endif
142
143 #ifdef JS_BASIC_STATS
144
145 #include <stdio.h>
146
147 typedef struct JSBasicStats {
148     uint32      num;
149     uint32      max;
150     double      sum;
151     double      sqsum;
152     uint32      logscale;           /* logarithmic scale: 0 (linear), 2, 10 */
153     uint32      hist[11];
154 } JSBasicStats;
155
156 #define JS_INIT_STATIC_BASIC_STATS  {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
157 #define JS_BASIC_STATS_INIT(bs)     memset((bs), 0, sizeof(JSBasicStats))
158
159 #define JS_BASIC_STATS_ACCUM(bs,val)                                          \
160     JS_BasicStatsAccum(bs, val)
161
162 #define JS_MeanAndStdDevBS(bs,sigma)                                          \
163     JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
164
165 extern void
166 JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
167
168 extern double
169 JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
170
171 extern void
172 JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
173
174 extern void
175 JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
176
177 #else
178
179 #define JS_BASIC_STATS_ACCUM(bs,val) /* nothing */
180
181 #endif /* JS_BASIC_STATS */
182
183
184 #if defined(DEBUG_notme) && defined(XP_UNIX)
185
186 typedef struct JSCallsite JSCallsite;
187
188 struct JSCallsite {
189     uint32      pc;
190     char        *name;
191     const char  *library;
192     int         offset;
193     JSCallsite  *parent;
194     JSCallsite  *siblings;
195     JSCallsite  *kids;
196     void        *handy;
197 };
198
199 extern JS_FRIEND_API(JSCallsite *)
200 JS_Backtrace(int skip);
201
202 extern JS_FRIEND_API(void)
203 JS_DumpBacktrace(JSCallsite *trace);
204 #endif
205
206 #if defined JS_USE_CUSTOM_ALLOCATOR
207
208 #include "jscustomallocator.h"
209
210 #else
211
212 static JS_INLINE void* js_malloc(size_t bytes) {
213     return malloc(bytes);
214 }
215
216 static JS_INLINE void* js_calloc(size_t bytes) {
217     return calloc(bytes, 1);
218 }
219
220 static JS_INLINE void* js_realloc(void* p, size_t bytes) {
221     return realloc(p, bytes);
222 }
223
224 static JS_INLINE void js_free(void* p) {
225     free(p);
226 }
227 #endif/* JS_USE_CUSTOM_ALLOCATOR */
228
229 JS_END_EXTERN_C
230
231 #ifdef __cplusplus
232
233 /* 
234  * Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
235  * failure instead of returning NULL, which is what SpiderMonkey expects.
236  * js_new()/js_array_new() should be used instead, and memory allocated with
237  * them should be deallocated with js_delete()/js_array_delete().
238  *
239  * If you have a class with a private constructor or destructor, you can
240  * make js_new/js_delete a friend.  This can be fiddly, and the interaction of
241  * template functions, friend functions and namespaces can overwhelm even
242  * modern compilers.  Manual inlining is probably easier.
243  *
244  * (If you're wondering why we can't just use the 'nothrow' variant of
245  * new/new[], it's because we want to mediate *all* allocations within
246  * SpiderMonkey, to satisfy any embedders using JS_USE_CUSTOM_ALLOCATOR.)
247  */
248
249 #define JS_NEW_BODY(t, parms)                                                 \
250     void *memory = js_malloc(sizeof(t));                                      \
251     return memory ? new(memory) t parms : NULL;
252
253 template <class T>
254 JS_ALWAYS_INLINE T *js_new() {
255     JS_NEW_BODY(T, ())
256 }
257
258 template <class T, class P1>
259 JS_ALWAYS_INLINE T *js_new(const P1 &p1) {
260     JS_NEW_BODY(T, (p1))
261 }
262
263 template <class T, class P1, class P2>
264 JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2) {
265     JS_NEW_BODY(T, (p1, p2))
266 }
267
268 template <class T, class P1, class P2, class P3>
269 JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3) {
270     JS_NEW_BODY(T, (p1, p2, p3))
271 }
272
273 template <class T, class P1, class P2, class P3, class P4>
274 JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) {
275     JS_NEW_BODY(T, (p1, p2, p3, p4))
276 }
277
278 /* ...add additional js_new()s as necessary... */
279
280 #undef JS_NEW_BODY
281
282 template <class T>
283 JS_ALWAYS_INLINE void js_delete(T *p) {
284     if (p) {
285         p->~T();
286         js_free(p);
287     }
288 }
289
290 static const int JSMinAlignment = 8;
291
292 template <class T>
293 JS_ALWAYS_INLINE T *js_array_new(size_t n) {
294         /* The length is stored just before the vector memory. */
295     uint64 numBytes64 = uint64(JSMinAlignment) + uint64(sizeof(T)) * uint64(n);
296     size_t numBytes = size_t(numBytes64);
297     if (numBytes64 != numBytes) {
298         JS_ASSERT(0);   /* we want to know if this happens in debug builds */
299         return NULL;
300     }
301     void *memory = js_malloc(numBytes);
302     if (!memory)
303         return NULL;
304         *(size_t *)memory = n;
305         memory = (void*)(uintptr_t(memory) + JSMinAlignment);
306     return new(memory) T[n];
307 }
308
309 template <class T>
310 JS_ALWAYS_INLINE void js_array_delete(T *p) {
311     if (p) {
312                 void* p0 = (void *)(uintptr_t(p) - JSMinAlignment);
313                 size_t n = *(size_t *)p0;
314                 for (size_t i = 0; i < n; i++)
315                         (p + i)->~T();
316                 js_free(p0);
317     }
318 }
319
320 /**
321  * The following classes are designed to cause assertions to detect
322  * inadvertent use of guard objects as temporaries.  In other words,
323  * when we have a guard object whose only purpose is its constructor and
324  * destructor (and is never otherwise referenced), the intended use
325  * might be:
326  *     JSAutoTempValueRooter tvr(cx, 1, &val);
327  * but is is easy to accidentally write:
328  *     JSAutoTempValueRooter(cx, 1, &val);
329  * which compiles just fine, but runs the destructor well before the
330  * intended time.
331  *
332  * They work by adding (#ifdef DEBUG) an additional parameter to the
333  * guard object's constructor, with a default value, so that users of
334  * the guard object's API do not need to do anything.  The default value
335  * of this parameter is a temporary object.  C++ (ISO/IEC 14882:1998),
336  * section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
337  * guarantee that temporaries are destroyed in the reverse of their
338  * construction order, but I actually can't find a statement that that
339  * is true in the general case (beyond the two specific cases mentioned
340  * there).  However, it seems to be true.
341  *
342  * These classes are intended to be used only via the macros immediately
343  * below them:
344  *   JS_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
345  *     variable, and should be put where a declaration of a private
346  *     member variable would be placed.
347  *   JS_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
348  *     parameters to each constructor of the guard object; it declares
349  *     (ifdef DEBUG) an additional parameter.
350  *   JS_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
351  *     constructor.  It uses the parameter declared by
352  *     JS_GUARD_OBJECT_NOTIFIER_PARAM.
353  */
354 #ifdef DEBUG
355 class JSGuardObjectNotifier
356 {
357 private:
358     bool* mStatementDone;
359 public:
360     JSGuardObjectNotifier() : mStatementDone(NULL) {}
361
362     ~JSGuardObjectNotifier() {
363         *mStatementDone = true;
364     }
365
366     void setStatementDone(bool *aStatementDone) {
367         mStatementDone = aStatementDone;
368     }
369 };
370
371 class JSGuardObjectNotificationReceiver
372 {
373 private:
374     bool mStatementDone;
375 public:
376     JSGuardObjectNotificationReceiver() : mStatementDone(false) {}
377
378     ~JSGuardObjectNotificationReceiver() {
379         /*
380          * Assert that the guard object was not used as a temporary.
381          * (Note that this assert might also fire if Init is not called
382          * because the guard object's implementation is not using the
383          * above macros correctly.)
384          */
385         JS_ASSERT(mStatementDone);
386     }
387
388     void Init(const JSGuardObjectNotifier &aNotifier) {
389         /*
390          * aNotifier is passed as a const reference so that we can pass a
391          * temporary, but we really intend it as non-const
392          */
393         const_cast<JSGuardObjectNotifier&>(aNotifier).
394             setStatementDone(&mStatementDone);
395     }
396 };
397
398 #define JS_DECL_USE_GUARD_OBJECT_NOTIFIER \
399     JSGuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
400 #define JS_GUARD_OBJECT_NOTIFIER_PARAM \
401     , const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
402 #define JS_GUARD_OBJECT_NOTIFIER_PARAM0 \
403     const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
404 #define JS_GUARD_OBJECT_NOTIFIER_INIT \
405     JS_BEGIN_MACRO _mCheckNotUsedAsTemporary.Init(_notifier); JS_END_MACRO
406
407 #else /* defined(DEBUG) */
408
409 #define JS_DECL_USE_GUARD_OBJECT_NOTIFIER
410 #define JS_GUARD_OBJECT_NOTIFIER_PARAM
411 #define JS_GUARD_OBJECT_NOTIFIER_PARAM0
412 #define JS_GUARD_OBJECT_NOTIFIER_INIT JS_BEGIN_MACRO JS_END_MACRO
413
414 #endif /* !defined(DEBUG) */
415
416 namespace js {
417
418 template <class T>
419 JS_ALWAYS_INLINE static void
420 PodZero(T *t)
421 {
422     memset(t, 0, sizeof(T));
423 }
424
425 template <class T>
426 JS_ALWAYS_INLINE static void
427 PodZero(T *t, size_t nelem)
428 {
429     memset(t, 0, nelem * sizeof(T));
430 }
431
432 /*
433  * Arrays implicitly convert to pointers to their first element, which is
434  * dangerous when combined with the above PodZero definitions. Adding an
435  * overload for arrays is ambiguous, so we need another identifier. The
436  * ambiguous overload is left to catch mistaken uses of PodZero; if you get a
437  * compile error involving PodZero and array types, use PodArrayZero instead.
438  */
439 template <class T, size_t N> static void PodZero(T (&)[N]);          /* undefined */
440 template <class T, size_t N> static void PodZero(T (&)[N], size_t);  /* undefined */
441
442 template <class T, size_t N>
443 JS_ALWAYS_INLINE static void
444 PodArrayZero(T (&t)[N])
445 {
446     memset(t, 0, N * sizeof(T));
447 }
448
449 template <class T>
450 JS_ALWAYS_INLINE static void
451 PodCopy(T *dst, const T *src, size_t nelem)
452 {
453     /* Cannot find portable word-sized abs(). */
454     JS_ASSERT_IF(dst >= src, size_t(dst - src) >= nelem);
455     JS_ASSERT_IF(src >= dst, size_t(src - dst) >= nelem);
456
457     if (nelem < 128) {
458         for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
459             *dst = *src;
460     } else {
461         memcpy(dst, src, nelem * sizeof(T));
462     }
463 }
464
465 } /* namespace js */
466
467 #endif /* defined(__cplusplus) */
468
469 #endif /* jsutil_h___ */