xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/objc/objc-map.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* objc-map.c -- Implementation of map data structures for ObjC compiler
2*8feb0f0bSmrg    Copyright (C) 2011-2020 Free Software Foundation, Inc.
336ac495dSmrg    Written by Nicola Pero <nicola.pero@meta-innovation.com>
436ac495dSmrg 
536ac495dSmrg This program is free software; you can redistribute it and/or modify it
636ac495dSmrg under the terms of the GNU Lesser Public License as published by the
736ac495dSmrg Free Software Foundation; either version 3, or (at your option) any
836ac495dSmrg later version.
936ac495dSmrg 
1036ac495dSmrg This program is distributed in the hope that it will be useful,
1136ac495dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
1236ac495dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1336ac495dSmrg GNU Lesser Public License for more details.
1436ac495dSmrg 
1536ac495dSmrg You should have received a copy of the GNU Lesser Public License
1636ac495dSmrg along with this program; if not, write to the Free Software
1736ac495dSmrg Foundation, 51 Franklin Street - Fifth Floor,
1836ac495dSmrg Boston, MA 02110-1301, USA.  */
1936ac495dSmrg 
2036ac495dSmrg #include "config.h"
2136ac495dSmrg #include "system.h"
2236ac495dSmrg #include "coretypes.h"
2336ac495dSmrg #include "tree.h"
2436ac495dSmrg #include "objc-map.h"
2536ac495dSmrg 
2636ac495dSmrg #define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); }
2736ac495dSmrg 
2836ac495dSmrg static
2936ac495dSmrg size_t
3036ac495dSmrg ATTRIBUTE_PURE
next_power_of_two(size_t x)3136ac495dSmrg next_power_of_two (size_t x)
3236ac495dSmrg {
3336ac495dSmrg   size_t result = 1;
3436ac495dSmrg 
3536ac495dSmrg   if (x < 2)
3636ac495dSmrg     return 2;
3736ac495dSmrg 
3836ac495dSmrg   /* Avoid the long calculation if x is already a power of two.  Since
3936ac495dSmrg      we internally always increase/shrink tables by powers of 2, the
4036ac495dSmrg      calculation should only be done once, when the table is first
4136ac495dSmrg      set up.  */
4236ac495dSmrg   if ((x & (x - 1)) == 0)
4336ac495dSmrg     return x;
4436ac495dSmrg 
4536ac495dSmrg   /* Calculate log_2 by counting how many times we can divide by 2
4636ac495dSmrg      before reaching 0.  */
4736ac495dSmrg   while (x > 0)
4836ac495dSmrg     {
4936ac495dSmrg       x = x >> 1;
5036ac495dSmrg       result = result << 1;
5136ac495dSmrg     }
5236ac495dSmrg   return result;
5336ac495dSmrg }
5436ac495dSmrg 
5536ac495dSmrg objc_map_t
objc_map_alloc_ggc(size_t initial_capacity)5636ac495dSmrg objc_map_alloc_ggc (size_t initial_capacity)
5736ac495dSmrg {
5836ac495dSmrg   objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
5936ac495dSmrg   if (map == NULL)
6036ac495dSmrg     OUT_OF_MEMORY;
6136ac495dSmrg 
6236ac495dSmrg   initial_capacity = next_power_of_two (initial_capacity);
6336ac495dSmrg 
6436ac495dSmrg   map->number_of_slots = initial_capacity;
6536ac495dSmrg   map->mask = initial_capacity - 1;
6636ac495dSmrg   map->maximum_load_factor = 70;
6736ac495dSmrg   map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
6836ac495dSmrg 
6936ac495dSmrg   map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
7036ac495dSmrg   map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
7136ac495dSmrg 
7236ac495dSmrg   if (map->slots == NULL)
7336ac495dSmrg     OUT_OF_MEMORY;
7436ac495dSmrg 
7536ac495dSmrg   if (map->values == NULL)
7636ac495dSmrg     OUT_OF_MEMORY;
7736ac495dSmrg 
7836ac495dSmrg   return map;
7936ac495dSmrg }
8036ac495dSmrg 
8136ac495dSmrg void
objc_map_set_maximum_load_factor(objc_map_t map,int number_between_zero_and_one_hundred)8236ac495dSmrg objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred)
8336ac495dSmrg {
8436ac495dSmrg   if (map->number_of_non_empty_slots != 0)
8536ac495dSmrg     return;
8636ac495dSmrg 
8736ac495dSmrg   map->maximum_load_factor = number_between_zero_and_one_hundred;
8836ac495dSmrg   map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100;
8936ac495dSmrg }
9036ac495dSmrg 
9136ac495dSmrg int
objc_map_maximum_load_factor(objc_map_t map)9236ac495dSmrg objc_map_maximum_load_factor (objc_map_t map)
9336ac495dSmrg {
9436ac495dSmrg   return map->maximum_load_factor;
9536ac495dSmrg }
9636ac495dSmrg 
9736ac495dSmrg static void
objc_map_private_resize(objc_map_t map,size_t new_number_of_slots)9836ac495dSmrg objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
9936ac495dSmrg {
10036ac495dSmrg   tree *old_slots = map->slots;
10136ac495dSmrg   tree *old_values = map->values;
10236ac495dSmrg   size_t i, old_number_of_slots = map->number_of_slots;
10336ac495dSmrg 
10436ac495dSmrg   if (new_number_of_slots < (map->number_of_non_empty_slots))
10536ac495dSmrg     new_number_of_slots = 2 * map->number_of_non_empty_slots;
10636ac495dSmrg 
10736ac495dSmrg   new_number_of_slots = next_power_of_two (new_number_of_slots);
10836ac495dSmrg 
10936ac495dSmrg   map->number_of_slots = new_number_of_slots;
11036ac495dSmrg   map->mask = map->number_of_slots - 1;
11136ac495dSmrg   map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
11236ac495dSmrg 
11336ac495dSmrg 
11436ac495dSmrg   map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
11536ac495dSmrg   map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
11636ac495dSmrg 
11736ac495dSmrg   if (map->slots == NULL)
11836ac495dSmrg     OUT_OF_MEMORY;
11936ac495dSmrg 
12036ac495dSmrg   if (map->values == NULL)
12136ac495dSmrg     OUT_OF_MEMORY;
12236ac495dSmrg 
12336ac495dSmrg   for (i = 0; i < old_number_of_slots; i++)
12436ac495dSmrg     if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT)
12536ac495dSmrg       {
12636ac495dSmrg 	size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask;
12736ac495dSmrg 
12836ac495dSmrg 	if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
12936ac495dSmrg 	  {
13036ac495dSmrg 	    map->slots[k] = old_slots[i];
13136ac495dSmrg 	    map->values[k] = old_values[i];
13236ac495dSmrg 	  }
13336ac495dSmrg 	else
13436ac495dSmrg 	  {
13536ac495dSmrg 	    size_t j = 1;
13636ac495dSmrg 	    while (1)
13736ac495dSmrg 	      {
13836ac495dSmrg 		k = (k + j) & map->mask;
13936ac495dSmrg 		if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
14036ac495dSmrg 		  {
14136ac495dSmrg 		    map->slots[k] = old_slots[i];
14236ac495dSmrg 		    map->values[k] = old_values[i];
14336ac495dSmrg 		    break;
14436ac495dSmrg 		  }
14536ac495dSmrg 		j++;
14636ac495dSmrg 	      }
14736ac495dSmrg 	  }
14836ac495dSmrg       }
14936ac495dSmrg 
15036ac495dSmrg   ggc_free (old_slots);
15136ac495dSmrg   ggc_free (old_values);
15236ac495dSmrg }
15336ac495dSmrg 
15436ac495dSmrg void
objc_map_private_grow(struct objc_map_private * map)15536ac495dSmrg objc_map_private_grow (struct objc_map_private *map)
15636ac495dSmrg {
15736ac495dSmrg   objc_map_private_resize (map, map->number_of_slots * 2);
15836ac495dSmrg }
15936ac495dSmrg 
16036ac495dSmrg #include "gt-objc-objc-map.h"
161