CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / tools / trace-malloc / leakstats.c
blob4c6174c5dae55084d008f173da37ab6d3a7ebc81
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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
14 * License.
16 * The Original Code is nsTraceMalloc.c/bloatblame.c code, released
17 * April 19, 2000.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 2000
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
25 * Brendan Eich, 14-April-2000
26 * L. David Baron, 2001-06-07, created leakstats.c based on bloatblame.c
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <errno.h>
45 #ifdef HAVE_GETOPT_H
46 #include <getopt.h>
47 #else
48 extern int getopt(int argc, char *const *argv, const char *shortopts);
49 extern char *optarg;
50 extern int optind;
51 #ifdef XP_WIN32
52 int optind=1;
53 #endif
54 #endif
55 #include <time.h>
56 #include "nsTraceMalloc.h"
57 #include "tmreader.h"
58 #include "prlog.h"
60 static char *program;
62 typedef struct handler_data {
63 uint32 current_heapsize;
64 uint32 max_heapsize;
65 uint32 bytes_allocated;
66 uint32 current_allocations;
67 uint32 total_allocations;
68 uint32 unmatched_frees;
69 int finished;
70 } handler_data;
72 static void handler_data_init(handler_data *data)
74 data->current_heapsize = 0;
75 data->max_heapsize = 0;
76 data->bytes_allocated = 0;
77 data->current_allocations = 0;
78 data->total_allocations = 0;
79 data->unmatched_frees = 0;
80 data->finished = 0;
83 static void handler_data_finish(handler_data *data)
87 static void my_tmevent_handler(tmreader *tmr, tmevent *event)
89 handler_data *data = (handler_data*) tmr->data;
91 switch (event->type) {
92 case TM_EVENT_REALLOC:
93 /* On Windows, original allocation could be before we overrode malloc */
94 if (event->u.alloc.oldserial != 0) {
95 data->current_heapsize -= event->u.alloc.oldsize;
96 --data->current_allocations;
97 } else {
98 ++data->unmatched_frees;
99 PR_ASSERT(event->u.alloc.oldsize == 0);
101 /* fall-through intentional */
102 case TM_EVENT_MALLOC:
103 case TM_EVENT_CALLOC:
104 ++data->current_allocations;
105 ++data->total_allocations;
106 data->bytes_allocated += event->u.alloc.size;
107 data->current_heapsize += event->u.alloc.size;
108 if (data->current_heapsize > data->max_heapsize)
109 data->max_heapsize = data->current_heapsize;
110 break;
111 case TM_EVENT_FREE:
112 /* On Windows, original allocation could be before we overrode malloc */
113 if (event->serial != 0) {
114 --data->current_allocations;
115 data->current_heapsize -= event->u.alloc.size;
116 } else {
117 ++data->unmatched_frees;
118 PR_ASSERT(event->u.alloc.size == 0);
120 break;
121 case TM_EVENT_STATS:
122 data->finished = 1;
123 break;
128 int main(int argc, char **argv)
130 int i, j, rv;
131 tmreader *tmr;
132 FILE *fp;
133 time_t start;
134 handler_data data;
136 program = *argv;
138 handler_data_init(&data);
139 tmr = tmreader_new(program, &data);
140 if (!tmr) {
141 perror(program);
142 exit(1);
145 start = time(NULL);
146 fprintf(stdout, "%s starting at %s", program, ctime(&start));
147 fflush(stdout);
149 argc -= optind;
150 argv += optind;
151 if (argc == 0) {
152 if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0)
153 exit(1);
154 } else {
155 for (i = j = 0; i < argc; i++) {
156 fp = fopen(argv[i], "r");
157 if (!fp) {
158 fprintf(stderr, "%s: can't open %s: %s\n",
159 program, argv[i], strerror(errno));
160 exit(1);
162 rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler);
163 if (rv < 0)
164 exit(1);
165 if (rv > 0)
166 j++;
167 fclose(fp);
169 if (j == 0)
170 exit(1);
173 if (!data.finished) {
174 fprintf(stderr, "%s: log file incomplete\n", program);
175 exit(1);
178 fprintf(stdout,
179 "Leaks: %u bytes, %u allocations\n"
180 "Maximum Heap Size: %u bytes\n"
181 "%u bytes were allocated in %u allocations.\n",
182 data.current_heapsize, data.current_allocations,
183 data.max_heapsize,
184 data.bytes_allocated, data.total_allocations);
185 if (data.unmatched_frees != 0)
186 fprintf(stdout,
187 "Logged %u free (or realloc) calls for which we missed the "
188 "original malloc.\n",
189 data.unmatched_frees);
191 handler_data_finish(&data);
192 tmreader_destroy(tmr);
194 exit(0);