Bug 588735 - Mirror glass caption buttons for rtl windows. r=roc, a=blocking-betaN.
[mozilla-central.git] / js / src / jsgcstats.cpp
blob0542f1838cb7a25780b533f4fcd06f25b6d626e9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99 ft=cpp:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * June 30, 2010
20 * The Initial Developer of the Original Code is
21 * the Mozilla Corporation.
23 * Contributor(s):
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "jstypes.h"
40 #include "jscntxt.h"
41 #include "jsgcstats.h"
42 #include "jsgc.h"
43 #include "jsxml.h"
44 #include "jsbuiltins.h"
46 using namespace js;
48 #if defined(JS_DUMP_CONSERVATIVE_GC_ROOTS) || defined(JS_GCMETER)
50 void
51 ConservativeGCStats::dump(FILE *fp)
53 size_t words = 0;
54 for (size_t i = 0; i != JS_ARRAY_LENGTH(counter); ++i)
55 words += counter[i];
57 #define ULSTAT(x) ((unsigned long)(x))
58 fprintf(fp, "CONSERVATIVE STACK SCANNING:\n");
59 fprintf(fp, " number of stack words: %lu\n", ULSTAT(words));
60 fprintf(fp, " excluded, low bit set: %lu\n", ULSTAT(counter[CGCT_LOWBITSET]));
61 fprintf(fp, " not withing a chunk: %lu\n", ULSTAT(counter[CGCT_NOTCHUNK]));
62 fprintf(fp, " not within arena range: %lu\n", ULSTAT(counter[CGCT_NOTARENA]));
63 fprintf(fp, " points to free arena: %lu\n", ULSTAT(counter[CGCT_FREEARENA]));
64 fprintf(fp, " excluded, wrong tag: %lu\n", ULSTAT(counter[CGCT_WRONGTAG]));
65 fprintf(fp, " excluded, not live: %lu\n", ULSTAT(counter[CGCT_NOTLIVE]));
66 fprintf(fp, " valid GC things: %lu\n", ULSTAT(counter[CGCT_VALID]));
67 #undef ULSTAT
69 #endif
71 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
72 void
73 GCMarker::dumpConservativeRoots()
75 if (!conservativeDumpFileName)
76 return;
78 FILE *fp;
79 if (!strcmp(conservativeDumpFileName, "stdout")) {
80 fp = stdout;
81 } else if (!strcmp(conservativeDumpFileName, "stderr")) {
82 fp = stderr;
83 } else if (!(fp = fopen(conservativeDumpFileName, "aw"))) {
84 fprintf(stderr,
85 "Warning: cannot open %s to dump the conservative roots\n",
86 conservativeDumpFileName);
87 return;
90 conservativeStats.dump(fp);
92 for (ConservativeRoot *i = conservativeRoots.begin();
93 i != conservativeRoots.end();
94 ++i) {
95 fprintf(fp, " %p: ", i->thing);
96 switch (i->traceKind) {
97 default:
98 JS_NOT_REACHED("Unknown trace kind");
100 case JSTRACE_OBJECT: {
101 JSObject *obj = (JSObject *) i->thing;
102 fprintf(fp, "object %s", obj->getClass()->name);
103 break;
105 case JSTRACE_STRING: {
106 JSString *str = (JSString *) i->thing;
107 char buf[50];
108 js_PutEscapedString(buf, sizeof buf, str, '"');
109 fprintf(fp, "string %s", buf);
110 break;
112 # if JS_HAS_XML_SUPPORT
113 case JSTRACE_XML: {
114 JSXML *xml = (JSXML *) i->thing;
115 fprintf(fp, "xml %u", (unsigned)xml->xml_class);
116 break;
118 # endif
120 fputc('\n', fp);
122 fputc('\n', fp);
124 if (fp != stdout && fp != stderr)
125 fclose(fp);
127 #endif /* JS_DUMP_CONSERVATIVE_GC_ROOTS */
129 #ifdef JS_GCMETER
131 void
132 UpdateArenaStats(JSGCArenaStats *st, uint32 nlivearenas, uint32 nkilledArenas,
133 uint32 nthings)
135 size_t narenas;
137 narenas = nlivearenas + nkilledArenas;
138 JS_ASSERT(narenas >= st->livearenas);
140 st->newarenas = narenas - st->livearenas;
141 st->narenas = narenas;
142 st->livearenas = nlivearenas;
143 if (st->maxarenas < narenas)
144 st->maxarenas = narenas;
145 st->totalarenas += narenas;
147 st->nthings = nthings;
148 if (st->maxthings < nthings)
149 st->maxthings = nthings;
150 st->totalthings += nthings;
153 JS_FRIEND_API(void)
154 js_DumpGCStats(JSRuntime *rt, FILE *fp)
156 static const char *const GC_ARENA_NAMES[] = {
157 "object",
158 "function",
159 #if JS_HAS_XML_SUPPORT
160 "xml",
161 #endif
162 "short string",
163 "string",
164 "external_string_0",
165 "external_string_1",
166 "external_string_2",
167 "external_string_3",
168 "external_string_4",
169 "external_string_5",
170 "external_string_6",
171 "external_string_7",
174 fprintf(fp, "\nGC allocation statistics:\n\n");
176 #define UL(x) ((unsigned long)(x))
177 #define ULSTAT(x) UL(rt->gcStats.x)
178 #define PERCENT(x,y) (100.0 * (double) (x) / (double) (y))
180 size_t sumArenas = 0;
181 size_t sumTotalArenas = 0;
182 size_t sumThings = 0;
183 size_t sumMaxThings = 0;
184 size_t sumThingSize = 0;
185 size_t sumTotalThingSize = 0;
186 size_t sumArenaCapacity = 0;
187 size_t sumTotalArenaCapacity = 0;
188 size_t sumAlloc = 0;
189 size_t sumLocalAlloc = 0;
190 size_t sumFail = 0;
191 size_t sumRetry = 0;
192 for (int i = 0; i < (int) FINALIZE_LIMIT; i++) {
193 size_t thingSize, thingsPerArena;
194 JSGCArenaStats *st;
195 thingSize = rt->gcArenaList[i].thingSize;
196 thingsPerArena = ThingsPerArena(thingSize);
197 st = &rt->gcArenaStats[i];
198 if (st->maxarenas == 0)
199 continue;
200 fprintf(fp,
201 "%s arenas (thing size %lu, %lu things per arena):",
202 GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena));
203 putc('\n', fp);
204 fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas));
205 fprintf(fp, " new arenas before GC: %lu (%.1f%%)\n",
206 UL(st->newarenas), PERCENT(st->newarenas, st->narenas));
207 fprintf(fp, " arenas after GC: %lu (%.1f%%)\n",
208 UL(st->livearenas), PERCENT(st->livearenas, st->narenas));
209 fprintf(fp, " max arenas: %lu\n", UL(st->maxarenas));
210 fprintf(fp, " things: %lu\n", UL(st->nthings));
211 fprintf(fp, " GC cell utilization: %.1f%%\n",
212 PERCENT(st->nthings, thingsPerArena * st->narenas));
213 fprintf(fp, " average cell utilization: %.1f%%\n",
214 PERCENT(st->totalthings, thingsPerArena * st->totalarenas));
215 fprintf(fp, " max things: %lu\n", UL(st->maxthings));
216 fprintf(fp, " alloc attempts: %lu\n", UL(st->alloc));
217 fprintf(fp, " alloc without locks: %lu (%.1f%%)\n",
218 UL(st->localalloc), PERCENT(st->localalloc, st->alloc));
219 sumArenas += st->narenas;
220 sumTotalArenas += st->totalarenas;
221 sumThings += st->nthings;
222 sumMaxThings += st->maxthings;
223 sumThingSize += thingSize * st->nthings;
224 sumTotalThingSize += size_t(thingSize * st->totalthings);
225 sumArenaCapacity += thingSize * thingsPerArena * st->narenas;
226 sumTotalArenaCapacity += thingSize * thingsPerArena * st->totalarenas;
227 sumAlloc += st->alloc;
228 sumLocalAlloc += st->localalloc;
229 sumFail += st->fail;
230 sumRetry += st->retry;
231 putc('\n', fp);
234 fputs("Never used arenas:\n", fp);
235 for (int i = 0; i < (int) FINALIZE_LIMIT; i++) {
236 size_t thingSize, thingsPerArena;
237 JSGCArenaStats *st;
238 thingSize = rt->gcArenaList[i].thingSize;
239 thingsPerArena = ThingsPerArena(thingSize);
240 st = &rt->gcArenaStats[i];
241 if (st->maxarenas != 0)
242 continue;
243 fprintf(fp,
244 "%s (thing size %lu, %lu things per arena)\n",
245 GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena));
247 fprintf(fp, "\nTOTAL STATS:\n");
248 fprintf(fp, " bytes allocated: %lu\n", UL(rt->gcBytes));
249 fprintf(fp, " total GC arenas: %lu\n", UL(sumArenas));
250 fprintf(fp, " max allocated arenas: %lu\n", ULSTAT(maxnallarenas));
251 fprintf(fp, " max allocated chunks: %lu\n", ULSTAT(maxnchunks));
252 fprintf(fp, " total GC things: %lu\n", UL(sumThings));
253 fprintf(fp, " max total GC things: %lu\n", UL(sumMaxThings));
254 fprintf(fp, " GC cell utilization: %.1f%%\n",
255 PERCENT(sumThingSize, sumArenaCapacity));
256 fprintf(fp, " average cell utilization: %.1f%%\n",
257 PERCENT(sumTotalThingSize, sumTotalArenaCapacity));
258 fprintf(fp, "allocation retries after GC: %lu\n", UL(sumRetry));
259 fprintf(fp, " alloc attempts: %lu\n", UL(sumAlloc));
260 fprintf(fp, " alloc without locks: %lu (%.1f%%)\n",
261 UL(sumLocalAlloc), PERCENT(sumLocalAlloc, sumAlloc));
262 fprintf(fp, " allocation failures: %lu\n", UL(sumFail));
263 fprintf(fp, " valid lock calls: %lu\n", ULSTAT(lock));
264 fprintf(fp, " valid unlock calls: %lu\n", ULSTAT(unlock));
265 fprintf(fp, " delayed tracing calls: %lu\n", ULSTAT(unmarked));
266 #ifdef DEBUG
267 fprintf(fp, " max trace later count: %lu\n", ULSTAT(maxunmarked));
268 #endif
269 fprintf(fp, "potentially useful GC calls: %lu\n", ULSTAT(poke));
270 fprintf(fp, " thing arenas freed so far: %lu\n", ULSTAT(afree));
271 rt->gcStats.conservative.dump(fp);
273 #undef UL
274 #undef ULSTAT
275 #undef PERCENT
277 #endif
279 #ifdef MOZ_GCTIMER
281 namespace js {
283 jsrefcount newChunkCount = 0;
284 jsrefcount destroyChunkCount = 0;
286 GCTimer::GCTimer() {
287 getFirstEnter();
288 memset(this, 0, sizeof(GCTimer));
289 enter = rdtsc();
292 uint64
293 GCTimer::getFirstEnter() {
294 static uint64 firstEnter = rdtsc();
295 return firstEnter;
298 void
299 GCTimer::finish(bool lastGC) {
300 end = rdtsc();
302 if (startMark > 0) {
303 if (JS_WANT_GC_SUITE_PRINT) {
304 fprintf(stderr, "%f %f %f\n",
305 (double)(end - enter) / 1e6,
306 (double)(startSweep - startMark) / 1e6,
307 (double)(sweepDestroyEnd - startSweep) / 1e6);
308 } else {
309 static FILE *gcFile;
311 if (!gcFile) {
312 gcFile = fopen("gcTimer.dat", "w");
314 fprintf(gcFile, " AppTime, Total, Mark, Sweep, FinObj,");
315 fprintf(gcFile, " FinStr, Destroy, newChunks, destoyChunks\n");
317 JS_ASSERT(gcFile);
318 fprintf(gcFile, "%12.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %7.1f, ",
319 (double)(enter - getFirstEnter()) / 1e6,
320 (double)(end - enter) / 1e6,
321 (double)(startSweep - startMark) / 1e6,
322 (double)(sweepDestroyEnd - startSweep) / 1e6,
323 (double)(sweepObjectEnd - startSweep) / 1e6,
324 (double)(sweepStringEnd - sweepObjectEnd) / 1e6,
325 (double)(sweepDestroyEnd - sweepStringEnd) / 1e6);
326 fprintf(gcFile, "%10d, %10d \n", newChunkCount,
327 destroyChunkCount);
328 fflush(gcFile);
330 if (lastGC) {
331 fclose(gcFile);
332 gcFile = NULL;
336 newChunkCount = 0;
337 destroyChunkCount = 0;
340 #ifdef JS_SCOPE_DEPTH_METER
341 void
342 DumpScopeDepthMeter(JSRuntime *rt)
344 static FILE *fp;
345 if (!fp)
346 fp = fopen("/tmp/scopedepth.stats", "w");
348 if (fp) {
349 JS_DumpBasicStats(&rt->protoLookupDepthStats, "proto-lookup depth", fp);
350 JS_DumpBasicStats(&rt->scopeSearchDepthStats, "scope-search depth", fp);
351 JS_DumpBasicStats(&rt->hostenvScopeDepthStats, "hostenv scope depth", fp);
352 JS_DumpBasicStats(&rt->lexicalScopeDepthStats, "lexical scope depth", fp);
354 putc('\n', fp);
355 fflush(fp);
358 #endif
360 #ifdef JS_DUMP_LOOP_STATS
361 void
362 DumpLoopStats(JSRuntime *rt)
364 static FILE *lsfp;
365 if (!lsfp)
366 lsfp = fopen("/tmp/loopstats", "w");
367 if (lsfp) {
368 JS_DumpBasicStats(&rt->loopStats, "loops", lsfp);
369 fflush(lsfp);
372 #endif
374 } /* namespace js */
375 #endif