1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
16 * The Original Code is Mozilla Communicator client code, released
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.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * PR assertion checker.
60 * Checks the assumption that JS_FUNC_TO_DATA_PTR and JS_DATA_TO_FUNC_PTR
61 * macros uses to implement casts between function and data pointers.
63 JS_STATIC_ASSERT(sizeof(void *) == sizeof(void (*)()));
65 JS_PUBLIC_API(void) JS_Assert(const char *s
, const char *file
, JSIntn ln
)
67 fprintf(stderr
, "Assertion failure: %s, at %s:%d\n", s
, file
, ln
);
71 * We used to call DebugBreak() on Windows, but amazingly, it causes
72 * the MSVS 2010 debugger not to be able to recover a call stack.
76 #elif defined(__APPLE__)
78 * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
81 *((int *) NULL
) = 0; /* To continue from here in GDB: "return" then "continue". */
82 raise(SIGABRT
); /* In case above statement gets nixed by the optimizer. */
84 raise(SIGABRT
); /* To continue from here in GDB: "signal 0". */
96 * Histogram bins count occurrences of values <= the bin label, as follows:
98 * linear: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or more
99 * 2**x: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or more
100 * 10**x: 0, 1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
102 * We wish to count occurrences of 0 and 1 values separately, always.
105 BinToVal(uintN logscale
, uintN bin
)
107 JS_ASSERT(bin
<= 10);
108 if (bin
<= 1 || logscale
== 0)
113 JS_ASSERT(logscale
== 10);
114 return (uint32
) pow(10.0, (double) bin
);
118 ValToBin(uintN logscale
, uint32 val
)
124 bin
= (logscale
== 10)
125 ? (uintN
) ceil(log10((double) val
))
127 ? (uintN
) JS_CeilingLog2(val
)
129 return JS_MIN(bin
, 10);
133 JS_BasicStatsAccum(JSBasicStats
*bs
, uint32 val
)
135 uintN oldscale
, newscale
, bin
;
142 bs
->sqsum
+= (double)val
* val
;
144 oldscale
= bs
->logscale
;
145 if (oldscale
!= 10) {
146 mean
= bs
->sum
/ bs
->num
;
147 if (bs
->max
> 16 && mean
> 8) {
148 newscale
= (bs
->max
> 1e6
&& mean
> 1000) ? 10 : 2;
149 if (newscale
!= oldscale
) {
150 uint32 newhist
[11], newbin
;
152 PodArrayZero(newhist
);
153 for (bin
= 0; bin
<= 10; bin
++) {
154 newbin
= ValToBin(newscale
, BinToVal(oldscale
, bin
));
155 newhist
[newbin
] += bs
->hist
[bin
];
157 memcpy(bs
->hist
, newhist
, sizeof bs
->hist
);
158 bs
->logscale
= newscale
;
163 bin
= ValToBin(bs
->logscale
, val
);
168 JS_MeanAndStdDev(uint32 num
, double sum
, double sqsum
, double *sigma
)
172 if (num
== 0 || sum
== 0) {
177 var
= num
* sqsum
- sum
* sum
;
178 if (var
< 0 || num
== 1)
181 var
/= (double)num
* (num
- 1);
183 /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
184 *sigma
= (var
!= 0) ? sqrt(var
) : 0;
189 JS_DumpBasicStats(JSBasicStats
*bs
, const char *title
, FILE *fp
)
193 mean
= JS_MeanAndStdDevBS(bs
, &sigma
);
194 fprintf(fp
, "\nmean %s %g, std. deviation %g, max %lu\n",
195 title
, mean
, sigma
, (unsigned long) bs
->max
);
196 JS_DumpHistogram(bs
, fp
);
200 JS_DumpHistogram(JSBasicStats
*bs
, FILE *fp
)
203 uint32 cnt
, max
, prev
, val
, i
;
206 for (bin
= 0, max
= 0, sum
= 0; bin
<= 10; bin
++) {
213 for (bin
= 0, prev
= 0; bin
<= 10; bin
++, prev
= val
) {
214 val
= BinToVal(bs
->logscale
, bin
);
217 fprintf(fp
, " [%6u]", val
);
219 fprintf(fp
, "[%6u, %6u]", prev
+ 1, val
);
220 fprintf(fp
, "%s %8u ", (bin
== 10) ? "+" : ":", cnt
);
222 if (max
> 1e6
&& mean
> 1e3
)
223 cnt
= (uint32
) ceil(log10((double) cnt
));
224 else if (max
> 16 && mean
> 8)
225 cnt
= JS_CeilingLog2(cnt
);
226 for (i
= 0; i
< cnt
; i
++)
233 #endif /* JS_BASIC_STATS */
235 #if defined(DEBUG_notme) && defined(XP_UNIX)
243 JSCallsite js_calltree_root
= {0, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
};
248 void **bpup
, **bpdown
, *pc
;
249 JSCallsite
*parent
, *site
, **csp
;
255 /* Reverse the stack frame list to avoid recursion. */
258 bpdown
= (void**) bp
[0];
259 bp
[0] = (void*) bpup
;
260 if ((void**) bpdown
[0] < bpdown
)
266 /* Reverse the stack again, finding and building a path in the tree. */
267 parent
= &js_calltree_root
;
269 bpup
= (void**) bp
[0];
270 bp
[0] = (void*) bpdown
;
274 while ((site
= *csp
) != NULL
) {
275 if (site
->pc
== (uint32
)pc
) {
276 /* Put the most recently used site at the front of siblings. */
277 *csp
= site
->siblings
;
278 site
->siblings
= parent
->kids
;
281 /* Site already built -- go up the stack. */
284 csp
= &site
->siblings
;
287 /* Check for recursion: see if pc is on our ancestor line. */
288 for (site
= parent
; site
; site
= site
->parent
) {
289 if (site
->pc
== (uint32
)pc
)
294 * Not in tree at all: let's find our symbolic callsite info.
295 * XXX static syms are masked by nearest lower global
297 info
.dli_fname
= info
.dli_sname
= NULL
;
298 ok
= dladdr(pc
, &info
);
300 fprintf(stderr
, "dladdr failed!\n");
304 /* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */
305 symbol
= info
.dli_sname
;
306 offset
= (char*)pc
- (char*)info
.dli_fbase
;
309 : JS_smprintf("%s+%X",
310 info
.dli_fname
? info
.dli_fname
: "main",
315 /* Create a new callsite record. */
316 site
= (JSCallsite
*) js_malloc(sizeof(JSCallsite
));
320 /* Insert the new site into the tree. */
321 site
->pc
= (uint32
)pc
;
323 site
->library
= info
.dli_fname
;
324 site
->offset
= offset
;
325 site
->parent
= parent
;
326 site
->siblings
= parent
->kids
;
339 JS_FRIEND_API(JSCallsite
*)
340 JS_Backtrace(int skip
)
344 /* Stack walking code adapted from Kipp's "leaky". */
346 __asm__( "movl %%ebp, %0" : "=g"(bp
));
347 #elif defined(__x86_64__)
348 __asm__( "movq %%rbp, %0" : "=g"(bp
));
351 * It would be nice if this worked uniformly, but at least on i386 and
352 * x86_64, it stopped working with gcc 4.1, because it points to the
353 * end of the saved registers instead of the start.
355 bp
= (void**) __builtin_frame_address(0);
357 while (--skip
>= 0) {
358 bpdown
= (void**) *bp
++;
368 JS_DumpBacktrace(JSCallsite
*trace
)
371 fprintf(stdout
, "%s [%s +0x%X]\n", trace
->name
, trace
->library
,
373 trace
= trace
->parent
;
377 #endif /* defined(DEBUG_notme) && defined(XP_UNIX) */