PR c/65345
[official-gcc.git] / gcc / objc / objc-map.c
blobc942cc257827b1d2bb01f9d15c1797b601fc52cc
1 /* objc-map.c -- Implementation of map data structures for ObjC compiler
2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
3 Written by Nicola Pero <nicola.pero@meta-innovation.com>
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Lesser Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
8 later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser Public License for more details.
15 You should have received a copy of the GNU Lesser Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street - Fifth Floor,
18 Boston, MA 02110-1301, USA. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "hash-set.h"
24 #include "machmode.h"
25 #include "vec.h"
26 #include "double-int.h"
27 #include "input.h"
28 #include "alias.h"
29 #include "symtab.h"
30 #include "options.h"
31 #include "wide-int.h"
32 #include "inchash.h"
33 #include "tree.h"
34 #include "ggc.h"
35 #include "objc-map.h"
37 #define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); }
39 static
40 size_t
41 ATTRIBUTE_PURE
42 next_power_of_two (size_t x)
44 size_t result = 1;
46 if (x < 2)
47 return 2;
49 /* Avoid the long calculation if x is already a power of two. Since
50 we internally always increase/shrink tables by powers of 2, the
51 calculation should only be done once, when the table is first
52 set up. */
53 if ((x & (x - 1)) == 0)
54 return x;
56 /* Calculate log_2 by counting how many times we can divide by 2
57 before reaching 0. */
58 while (x > 0)
60 x = x >> 1;
61 result = result << 1;
63 return result;
66 objc_map_t
67 objc_map_alloc_ggc (size_t initial_capacity)
69 objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
70 if (map == NULL)
71 OUT_OF_MEMORY;
73 initial_capacity = next_power_of_two (initial_capacity);
75 map->number_of_slots = initial_capacity;
76 map->mask = initial_capacity - 1;
77 map->maximum_load_factor = 70;
78 map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
80 map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
81 map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
83 if (map->slots == NULL)
84 OUT_OF_MEMORY;
86 if (map->values == NULL)
87 OUT_OF_MEMORY;
89 return map;
92 void
93 objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred)
95 if (map->number_of_non_empty_slots != 0)
96 return;
98 map->maximum_load_factor = number_between_zero_and_one_hundred;
99 map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100;
103 objc_map_maximum_load_factor (objc_map_t map)
105 return map->maximum_load_factor;
108 static void
109 objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
111 tree *old_slots = map->slots;
112 tree *old_values = map->values;
113 size_t i, old_number_of_slots = map->number_of_slots;
115 if (new_number_of_slots < (map->number_of_non_empty_slots))
116 new_number_of_slots = 2 * map->number_of_non_empty_slots;
118 new_number_of_slots = next_power_of_two (new_number_of_slots);
120 map->number_of_slots = new_number_of_slots;
121 map->mask = map->number_of_slots - 1;
122 map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
125 map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
126 map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
128 if (map->slots == NULL)
129 OUT_OF_MEMORY;
131 if (map->values == NULL)
132 OUT_OF_MEMORY;
134 for (i = 0; i < old_number_of_slots; i++)
135 if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT)
137 size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask;
139 if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
141 map->slots[k] = old_slots[i];
142 map->values[k] = old_values[i];
144 else
146 size_t j = 1;
147 while (1)
149 k = (k + j) & map->mask;
150 if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
152 map->slots[k] = old_slots[i];
153 map->values[k] = old_values[i];
154 break;
156 j++;
161 ggc_free (old_slots);
162 ggc_free (old_values);
165 void
166 objc_map_private_grow (struct objc_map_private *map)
168 objc_map_private_resize (map, map->number_of_slots * 2);
171 #include "gt-objc-objc-map.h"