1 /* Vector API for GNU compiler.
2    Copyright (C) 2004-2016 Free Software Foundation, Inc.
3    Contributed by Nathan Sidwell <nathan@codesourcery.com>
4    Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
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
10 Software Foundation; either version 3, or (at your option) any later
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
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
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
27 #include "config.h"
28 #endif
29 
30 #include "system.h"
31 #include "coretypes.h"
32 #include "hash-table.h"
33 
34 /* vNULL is an empty type with a template cast operation that returns
35    a zero-initialized vec<T, A, L> instance.  Use this when you want
36    to assign nil values to new vec instances or pass a nil vector as
37    a function call argument.
38 
39    We use this technique because vec<T, A, L> must be PODs (they are
40    stored in unions and passed in vararg functions), this means that
41    they cannot have ctors/dtors.  */
42 vnull vNULL;
43 
44 /* Vector memory usage.  */
45 struct vec_usage: public mem_usage
46 {
47   /* Default constructor.  */
vec_usagevec_usage48   vec_usage (): m_items (0), m_items_peak (0) {}
49 
50   /* Constructor.  */
vec_usagevec_usage51   vec_usage (size_t allocated, size_t times, size_t peak,
52 	     size_t items, size_t items_peak)
53     : mem_usage (allocated, times, peak),
54     m_items (items), m_items_peak (items_peak) {}
55 
56   /* Comparison operator.  */
57   inline bool
58   operator< (const vec_usage &second) const
59   {
60     return (m_allocated == second.m_allocated ?
61 	    (m_peak == second.m_peak ? m_times < second.m_times
62 	     : m_peak < second.m_peak) : m_allocated < second.m_allocated);
63   }
64 
65   /* Sum the usage with SECOND usage.  */
66   vec_usage
67   operator+ (const vec_usage &second)
68   {
69     return vec_usage (m_allocated + second.m_allocated,
70 		      m_times + second.m_times,
71 		      m_peak + second.m_peak,
72 		      m_items + second.m_items,
73 		      m_items_peak + second.m_items_peak);
74   }
75 
76   /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
77   inline void
dumpvec_usage78   dump (mem_location *loc, mem_usage &total) const
79   {
80     char s[4096];
81     sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
82 	     loc->m_line, loc->m_function);
83 
84     s[48] = '\0';
85 
86     fprintf (stderr, "%-48s %10li:%4.1f%%%10li%10li:%4.1f%%%11li%11li\n", s,
87 	     (long)m_allocated, m_allocated * 100.0 / total.m_allocated,
88 	     (long)m_peak, (long)m_times, m_times * 100.0 / total.m_times,
89 	     (long)m_items, (long)m_items_peak);
90   }
91 
92   /* Dump footer.  */
93   inline void
dump_footervec_usage94   dump_footer ()
95   {
96     print_dash_line ();
97     fprintf (stderr, "%s%55li%25li%17li\n", "Total", (long)m_allocated,
98 	     (long)m_times, (long)m_items);
99     print_dash_line ();
100   }
101 
102   /* Dump header with NAME.  */
103   static inline void
dump_headervec_usage104   dump_header (const char *name)
105   {
106     fprintf (stderr, "%-48s %11s%15s%10s%17s%11s\n", name, "Leak", "Peak",
107 	     "Times", "Leak items", "Peak items");
108     print_dash_line ();
109   }
110 
111   /* Compare wrapper used by qsort method.  */
112   static int
comparevec_usage113   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;
127 };
128 
129 /* Vector memory description.  */
130 static mem_alloc_description <vec_usage> vec_mem_desc;
131 
132 /* Account the overhead.  */
133 
134 void
register_overhead(void * ptr,size_t size,size_t elements MEM_STAT_DECL)135 vec_prefix::register_overhead (void *ptr, size_t size, size_t elements
136 			       MEM_STAT_DECL)
137 {
138   vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
139 				    FINAL_PASS_MEM_STAT);
140   vec_usage *usage = vec_mem_desc.register_instance_overhead (size, ptr);
141   usage->m_items += elements;
142   if (usage->m_items_peak < usage->m_items)
143     usage->m_items_peak = usage->m_items;
144 }
145 
146 /* Notice that the memory allocated for the vector has been freed.  */
147 
148 void
release_overhead(void * ptr,size_t size,bool in_dtor MEM_STAT_DECL)149 vec_prefix::release_overhead (void *ptr, size_t size, bool in_dtor
150 			      MEM_STAT_DECL)
151 {
152   if (!vec_mem_desc.contains_descriptor_for_instance (ptr))
153     vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN,
154 				      false FINAL_PASS_MEM_STAT);
155   vec_mem_desc.release_instance_overhead (ptr, size, in_dtor);
156 }
157 
158 
159 /* Calculate the number of slots to reserve a vector, making sure that
160    it is of at least DESIRED size by growing ALLOC exponentially.  */
161 
162 unsigned
calculate_allocation_1(unsigned alloc,unsigned desired)163 vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
164 {
165   /* We must have run out of room.  */
166   gcc_assert (alloc < desired);
167 
168   /* Exponential growth. */
169   if (!alloc)
170     alloc = 4;
171   else if (alloc < 16)
172     /* Double when small.  */
173     alloc = alloc * 2;
174   else
175     /* Grow slower when large.  */
176     alloc = (alloc * 3 / 2);
177 
178   /* If this is still too small, set it to the right size. */
179   if (alloc < desired)
180     alloc = desired;
181   return alloc;
182 }
183 
184 /* Dump per-site memory statistics.  */
185 
186 void
dump_vec_loc_statistics(void)187 dump_vec_loc_statistics (void)
188 {
189   vec_mem_desc.dump (VEC_ORIGIN);
190 }
191