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