vec.c 5.4 KB
Newer Older
1
/* Vector API for GNU compiler.
Jakub Jelinek committed
2
   Copyright (C) 2004-2015 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 7 8 9

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
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 12 13 14 15 16 17 18
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
21

22 23 24 25 26
/* This file is compiled twice: once for the generator programs
   once for the compiler.  */
#ifdef GENERATOR_FILE
#include "bconfig.h"
#else
27
#include "config.h"
28 29
#endif

30
#include "system.h"
31
#include "coretypes.h"
32
#include "hash-table.h"
33

34 35 36 37 38 39 40 41 42 43
/* vNULL is an empty type with a template cast operation that returns
   a zero-initialized vec<T, A, L> instance.  Use this when you want
   to assign nil values to new vec instances or pass a nil vector as
   a function call argument.

   We use this technique because vec<T, A, L> must be PODs (they are
   stored in unions and passed in vararg functions), this means that
   they cannot have ctors/dtors.  */
vnull vNULL;

44 45
/* Vector memory usage.  */
struct vec_usage: public mem_usage
46
{
47 48 49 50 51 52 53 54 55 56
  /* Default constructor.  */
  vec_usage (): m_items (0), m_items_peak (0) {}

  /* Constructor.  */
  vec_usage (size_t allocated, size_t times, size_t peak,
	     size_t items, size_t items_peak)
    : mem_usage (allocated, times, peak),
    m_items (items), m_items_peak (items_peak) {}

  /* Comparison operator.  */
57 58
  inline bool
  operator< (const vec_usage &second) const
59 60 61 62 63 64 65
  {
    return (m_allocated == second.m_allocated ?
	    (m_peak == second.m_peak ? m_times < second.m_times
	     : m_peak < second.m_peak) : m_allocated < second.m_allocated);
  }

  /* Sum the usage with SECOND usage.  */
66 67
  vec_usage
  operator+ (const vec_usage &second)
68 69 70 71 72 73 74 75 76
  {
    return vec_usage (m_allocated + second.m_allocated,
		      m_times + second.m_times,
		      m_peak + second.m_peak,
		      m_items + second.m_items,
		      m_items_peak + second.m_items_peak);
  }

  /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
77 78
  inline void
  dump (mem_location *loc, mem_usage &total) const
79 80 81 82 83 84 85 86 87 88 89 90 91 92
  {
    char s[4096];
    sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
	     loc->m_line, loc->m_function);

    s[48] = '\0';

    fprintf (stderr, "%-48s %10li:%4.1f%%%10li%10li:%4.1f%%%11li%11li\n", s,
	     (long)m_allocated, m_allocated * 100.0 / total.m_allocated,
	     (long)m_peak, (long)m_times, m_times * 100.0 / total.m_times,
	     (long)m_items, (long)m_items_peak);
  }

  /* Dump footer.  */
93 94
  inline void
  dump_footer ()
95 96 97 98 99 100 101 102
  {
    print_dash_line ();
    fprintf (stderr, "%s%55li%25li%17li\n", "Total", (long)m_allocated,
	     (long)m_times, (long)m_items);
    print_dash_line ();
  }

  /* Dump header with NAME.  */
103 104
  static inline void
  dump_header (const char *name)
105 106 107 108 109 110 111
  {
    fprintf (stderr, "%-48s %11s%15s%10s%17s%11s\n", name, "Leak", "Peak",
	     "Times", "Leak items", "Peak items");
    print_dash_line ();
  }

  /* Compare wrapper used by qsort method.  */
112 113
  static int
  compare (const void *first, const void *second)
114 115 116 117 118 119 120 121 122 123 124 125 126
  {
    typedef std::pair<mem_location *, vec_usage *> mem_pair_t;

    const mem_pair_t f = *(const mem_pair_t *)first;
    const mem_pair_t s = *(const mem_pair_t *)second;

    return (*f.second) < (*s.second);
  }

  /* Current number of items allocated.  */
  size_t m_items;
  /* Peak value of number of allocated items.  */
  size_t m_items_peak;
127 128
};

129 130
/* Vector memory description.  */
static mem_alloc_description <vec_usage> vec_mem_desc;
131 132

/* Account the overhead.  */
133 134

void
135 136
vec_prefix::register_overhead (void *ptr, size_t size, size_t elements
			       MEM_STAT_DECL)
137
{
138 139
  vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
				    FINAL_PASS_MEM_STAT);
140 141 142 143
  vec_usage *usage = vec_mem_desc.register_instance_overhead (size, ptr);
  usage->m_items += elements;
  if (usage->m_items_peak < usage->m_items)
    usage->m_items_peak = usage->m_items;
144 145
}

146 147 148
/* Notice that the memory allocated for the vector has been freed.  */

void
149 150
vec_prefix::release_overhead (void *ptr, size_t size, bool in_dtor
			      MEM_STAT_DECL)
151
{
152
  if (!vec_mem_desc.contains_descriptor_for_instance (ptr))
153 154
    vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN,
				      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
163
vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
164 165
{
  /* We must have run out of room.  */
166 167 168 169 170 171 172 173
  gcc_assert (alloc < desired);

  /* Exponential growth. */
  if (!alloc)
    alloc = 4;
  else if (alloc < 16)
    /* Double when small.  */
    alloc = alloc * 2;
174
  else
175 176 177 178 179 180
    /* Grow slower when large.  */
    alloc = (alloc * 3 / 2);

  /* If this is still too small, set it to the right size. */
  if (alloc < desired)
    alloc = desired;
181 182 183
  return alloc;
}

184
/* Dump per-site memory statistics.  */
185

186 187 188
void
dump_vec_loc_statistics (void)
{
189
  vec_mem_desc.dump (VEC_ORIGIN);
190
}