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