]>
Commit | Line | Data |
---|---|---|
ada55151 | 1 | /* Vector API for GNU compiler. |
5624e564 | 2 | Copyright (C) 2004-2015 Free Software Foundation, Inc. |
ada55151 | 3 | Contributed by Nathan Sidwell <nathan@codesourcery.com> |
0823efed | 4 | Re-implemented in C++ by Diego Novillo <dnovillo@google.com> |
ada55151 NS |
5 | |
6 | This file is part of GCC. | |
7 | ||
8 | GCC is free software; you can redistribute it and/or modify it under | |
9 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 10 | Software Foundation; either version 3, or (at your option) any later |
ada55151 NS |
11 | version. |
12 | ||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
ada55151 | 21 | |
2d5bc016 DD |
22 | /* This file is compiled twice: once for the generator programs |
23 | once for the compiler. */ | |
24 | #ifdef GENERATOR_FILE | |
25 | #include "bconfig.h" | |
26 | #else | |
ada55151 | 27 | #include "config.h" |
2d5bc016 DD |
28 | #endif |
29 | ||
ada55151 | 30 | #include "system.h" |
fc64b448 | 31 | #include "coretypes.h" |
ada55151 NS |
32 | #include "ggc.h" |
33 | #include "vec.h" | |
718f9c0f | 34 | #include "diagnostic-core.h" |
d3492572 | 35 | #include "hashtab.h" |
2d44c7de ML |
36 | #include "mem-stats.h" |
37 | #include "hash-map.h" | |
38 | #include "mem-stats.h" | |
ada55151 | 39 | |
6e1aa848 DN |
40 | /* vNULL is an empty type with a template cast operation that returns |
41 | a zero-initialized vec<T, A, L> instance. Use this when you want | |
42 | to assign nil values to new vec instances or pass a nil vector as | |
43 | a function call argument. | |
44 | ||
45 | We use this technique because vec<T, A, L> must be PODs (they are | |
46 | stored in unions and passed in vararg functions), this means that | |
47 | they cannot have ctors/dtors. */ | |
48 | vnull vNULL; | |
49 | ||
2d44c7de ML |
50 | /* Vector memory usage. */ |
51 | struct vec_usage: public mem_usage | |
d3492572 | 52 | { |
2d44c7de ML |
53 | /* Default constructor. */ |
54 | vec_usage (): m_items (0), m_items_peak (0) {} | |
55 | ||
56 | /* Constructor. */ | |
57 | vec_usage (size_t allocated, size_t times, size_t peak, | |
58 | size_t items, size_t items_peak) | |
59 | : mem_usage (allocated, times, peak), | |
60 | m_items (items), m_items_peak (items_peak) {} | |
61 | ||
62 | /* Comparison operator. */ | |
63 | inline bool operator< (const vec_usage &second) const | |
64 | { | |
65 | return (m_allocated == second.m_allocated ? | |
66 | (m_peak == second.m_peak ? m_times < second.m_times | |
67 | : m_peak < second.m_peak) : m_allocated < second.m_allocated); | |
68 | } | |
69 | ||
70 | /* Sum the usage with SECOND usage. */ | |
71 | vec_usage operator+ (const vec_usage &second) | |
72 | { | |
73 | return vec_usage (m_allocated + second.m_allocated, | |
74 | m_times + second.m_times, | |
75 | m_peak + second.m_peak, | |
76 | m_items + second.m_items, | |
77 | m_items_peak + second.m_items_peak); | |
78 | } | |
79 | ||
80 | /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */ | |
81 | inline void dump (mem_location *loc, mem_usage &total) const | |
82 | { | |
83 | char s[4096]; | |
84 | sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (), | |
85 | loc->m_line, loc->m_function); | |
86 | ||
87 | s[48] = '\0'; | |
88 | ||
89 | fprintf (stderr, "%-48s %10li:%4.1f%%%10li%10li:%4.1f%%%11li%11li\n", s, | |
90 | (long)m_allocated, m_allocated * 100.0 / total.m_allocated, | |
91 | (long)m_peak, (long)m_times, m_times * 100.0 / total.m_times, | |
92 | (long)m_items, (long)m_items_peak); | |
93 | } | |
94 | ||
95 | /* Dump footer. */ | |
96 | inline void dump_footer () | |
97 | { | |
98 | print_dash_line (); | |
99 | fprintf (stderr, "%s%55li%25li%17li\n", "Total", (long)m_allocated, | |
100 | (long)m_times, (long)m_items); | |
101 | print_dash_line (); | |
102 | } | |
103 | ||
104 | /* Dump header with NAME. */ | |
105 | static inline void dump_header (const char *name) | |
106 | { | |
107 | fprintf (stderr, "%-48s %11s%15s%10s%17s%11s\n", name, "Leak", "Peak", | |
108 | "Times", "Leak items", "Peak items"); | |
109 | print_dash_line (); | |
110 | } | |
111 | ||
112 | /* Compare wrapper used by qsort method. */ | |
113 | static int compare (const void *first, const void *second) | |
114 | { | |
115 | typedef std::pair<mem_location *, vec_usage *> mem_pair_t; | |
116 | ||
117 | const mem_pair_t f = *(const mem_pair_t *)first; | |
118 | const mem_pair_t s = *(const mem_pair_t *)second; | |
119 | ||
120 | return (*f.second) < (*s.second); | |
121 | } | |
122 | ||
123 | /* Current number of items allocated. */ | |
124 | size_t m_items; | |
125 | /* Peak value of number of allocated items. */ | |
126 | size_t m_items_peak; | |
d3492572 JH |
127 | }; |
128 | ||
2d44c7de ML |
129 | /* Vector memory description. */ |
130 | static mem_alloc_description <vec_usage> vec_mem_desc; | |
d3492572 JH |
131 | |
132 | /* Account the overhead. */ | |
9771b263 DN |
133 | |
134 | void | |
2d44c7de ML |
135 | vec_prefix::register_overhead (void *ptr, size_t size, size_t elements |
136 | MEM_STAT_DECL) | |
d3492572 | 137 | { |
2d44c7de ML |
138 | vec_mem_desc.register_descriptor (ptr, VEC, false FINAL_PASS_MEM_STAT); |
139 | vec_usage *usage = vec_mem_desc.register_instance_overhead (size, ptr); | |
140 | usage->m_items += elements; | |
141 | if (usage->m_items_peak < usage->m_items) | |
142 | usage->m_items_peak = usage->m_items; | |
d3492572 JH |
143 | } |
144 | ||
9771b263 DN |
145 | /* Notice that the memory allocated for the vector has been freed. */ |
146 | ||
147 | void | |
2d44c7de ML |
148 | vec_prefix::release_overhead (void *ptr, size_t size, bool in_dtor |
149 | MEM_STAT_DECL) | |
d3492572 | 150 | { |
2d44c7de ML |
151 | if (!vec_mem_desc.contains_descriptor_for_instance (ptr)) |
152 | vec_mem_desc.register_descriptor (ptr, VEC, false FINAL_PASS_MEM_STAT); | |
153 | vec_mem_desc.release_instance_overhead (ptr, size, in_dtor); | |
d3492572 JH |
154 | } |
155 | ||
d3492572 | 156 | |
9771b263 | 157 | /* Calculate the number of slots to reserve a vector, making sure that |
3a938d75 | 158 | it is of at least DESIRED size by growing ALLOC exponentially. */ |
d4e6fecb | 159 | |
9771b263 | 160 | unsigned |
3a938d75 | 161 | vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired) |
d4e6fecb | 162 | { |
d4e6fecb | 163 | /* We must have run out of room. */ |
3a938d75 RB |
164 | gcc_assert (alloc < desired); |
165 | ||
166 | /* Exponential growth. */ | |
167 | if (!alloc) | |
168 | alloc = 4; | |
169 | else if (alloc < 16) | |
170 | /* Double when small. */ | |
171 | alloc = alloc * 2; | |
d4e6fecb | 172 | else |
3a938d75 RB |
173 | /* Grow slower when large. */ |
174 | alloc = (alloc * 3 / 2); | |
175 | ||
176 | /* If this is still too small, set it to the right size. */ | |
177 | if (alloc < desired) | |
178 | alloc = desired; | |
d4e6fecb NS |
179 | return alloc; |
180 | } | |
181 | ||
d3492572 | 182 | /* Dump per-site memory statistics. */ |
7aa6d18a | 183 | |
d3492572 JH |
184 | void |
185 | dump_vec_loc_statistics (void) | |
186 | { | |
2d44c7de | 187 | vec_mem_desc.dump (VEC); |
d3492572 | 188 | } |