Changeset 1902 for trunk/src/kmk/hash.c


Ignore:
Timestamp:
Oct 21, 2008, 5:57:00 AM (17 years ago)
Author:
bird
Message:

kmk: Moved the strcache hash optimizations into the hash code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/hash.c

    r1864 r1902  
    1919#include "make.h"
    2020#include "hash.h"
     21#ifdef CONFIG_WITH_STRCACHE2
     22# include <assert.h>
     23#endif
     24
    2125
    2226#define CALLOC(t, n) ((t *) calloc (sizeof (t), (n)))
     
    6266  ht->ht_hash_2 = hash_2;
    6367  ht->ht_compare = hash_cmp;
    64 }
     68#ifdef CONFIG_WITH_STRCACHE2
     69  ht->ht_strcache = 0;
     70  ht->ht_off_string = 0;
     71#endif
     72}
     73
     74#ifdef CONFIG_WITH_STRCACHE2
     75/* Same as hash_init, except that no callbacks are needed since all
     76   keys - including the ones being searched for - are from a string
     77   cache.  This means that any give string will only have one pointer
     78   value and that the hash and length can be retrived very cheaply,
     79   thus permitting some nice optimizations.
     80
     81   STRCACHE points to the string cache, while OFF_STRING gives the
     82   offset of the string pointer in the item structures the hash table
     83   entries points to.  */
     84void hash_init_strcached (struct hash_table *ht, unsigned long size,
     85                          struct strcache2 *strcache, unsigned int off_string)
     86{
     87  hash_init (ht, size, 0, 0, 0);
     88  ht->ht_strcache = strcache;
     89  ht->ht_off_string = off_string;
     90}
     91#endif /* CONFIG_WITH_STRCACHE2 */
    6592
    6693/* Load an array of items into `ht'.  */
     
    7198{
    7299  char *items = (char *) item_table;
     100#ifndef CONFIG_WITH_STRCACHE2
    73101  while (cardinality--)
    74102    {
     
    76104      items += size;
    77105    }
     106#else  /* CONFIG_WITH_STRCACHE2 */
     107  if (ht->ht_strcache)
     108    while (cardinality--)
     109      {
     110        hash_insert_strcached (ht, items);
     111        items += size;
     112      }
     113  else
     114    while (cardinality--)
     115      {
     116        hash_insert (ht, items);
     117        items += size;
     118      }
     119#endif /* CONFIG_WITH_STRCACHE2 */
    78120}
    79121
     
    90132  unsigned int hash_2 = 0;
    91133  unsigned int hash_1 = (*ht->ht_hash_1) (key);
     134
     135#ifdef CONFIG_WITH_STRCACHE2
     136  assert (ht->ht_strcache == 0);
     137#endif
    92138
    93139  ht->ht_lookups++;
     
    124170}
    125171
    126 #ifdef CONFIG_WITH_VALUE_LENGTH
    127 /* A variant of hash_find_slot that takes the hash values as arguments.
    128    The HASH_2 argument is optional, pass 0 if not available.
    129    Not having to call ht_hash_1 and perhaps also not ht_hash_2 does save
    130    a whole bunch of cycles in some of the kBuild use cases (strcache sees
    131    serious usage there). */
     172#ifdef CONFIG_WITH_STRCACHE2
     173/* hash_find_slot version for tables created with hash_init_strcached.  */
    132174void **
    133 hash_find_slot_prehashed (struct hash_table *ht, const void *key,
    134                           unsigned int hash_1, unsigned int hash_2)
     175hash_find_slot_strcached (struct hash_table *ht, const void *key)
    135176{
    136177  void **slot;
    137178  void **deleted_slot = 0;
     179  const char *str1 = *(const char **)((const char *)key + ht->ht_off_string);
     180  const char *str2;
     181  unsigned int hash_1 = strcache2_get_ptr_hash (ht->ht_strcache, str1);
     182  unsigned int hash_2;
     183
     184#ifdef CONFIG_WITH_STRCACHE2
     185  assert (ht->ht_strcache != 0);
     186#endif
    138187
    139188  ht->ht_lookups++;
     
    141190  make_stats_ht_lookups++;
    142191#endif
     192
     193  /* first iteration unrolled. */
     194
     195  hash_1 &= (ht->ht_size - 1);
     196  slot = &ht->ht_vec[hash_1];
     197  if (*slot == 0)
     198    return slot;
     199  if (*slot != hash_deleted_item)
     200    {
     201      str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string);
     202      if (str1 == str2)
     203        return slot;
     204
     205      ht->ht_collisions++;
     206#ifdef CONFIG_WITH_MAKE_STATS
     207      make_stats_ht_collisions++;
     208#endif
     209    }
     210  else
     211    deleted_slot = slot;
     212
     213  /* the rest of the loop. */
     214
     215  hash_2 = strcache2_get_hash1 (ht->ht_strcache, str1) | 1;
     216  hash_1 += hash_2;
    143217  for (;;)
    144218    {
     
    155229      else
    156230        {
    157           if (key == *slot)
     231          str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string);
     232          if (str1 == str2)
    158233            return slot;
    159           if ((*ht->ht_compare) (key, *slot) == 0)
    160             return slot;
     234
    161235          ht->ht_collisions++;
    162236#ifdef CONFIG_WITH_MAKE_STATS
     
    164238#endif
    165239        }
    166       if (!hash_2)
    167           hash_2 = (*ht->ht_hash_2) (key) | 1;
     240
    168241      hash_1 += hash_2;
    169242    }
    170243}
    171 
    172 #endif /* CONFIG_WITH_VALUE_LENGTH */
     244#endif /* CONFIG_WITH_STRCACHE2 */
    173245
    174246void *
     
    178250  return ((HASH_VACANT (*slot)) ? 0 : *slot);
    179251}
     252
     253#ifdef CONFIG_WITH_STRCACHE2
     254void *
     255hash_find_item_strcached (struct hash_table *ht, const void *key)
     256{
     257  void **slot = hash_find_slot_strcached (ht, key);
     258  return ((HASH_VACANT (*slot)) ? 0 : *slot);
     259}
     260#endif /* CONFIG_WITH_STRCACHE2 */
    180261
    181262void *
     
    188269}
    189270
     271#ifdef CONFIG_WITH_STRCACHE2
     272void *
     273hash_insert_strcached (struct hash_table *ht, const void *item)
     274{
     275  void **slot = hash_find_slot_strcached (ht, item);
     276  const void *old_item = slot ? *slot : 0;
     277  hash_insert_at (ht, item, slot);
     278  return (void *)((HASH_VACANT (old_item)) ? 0 : old_item);
     279}
     280#endif /* CONFIG_WITH_STRCACHE2 */
     281
    190282void *
    191283hash_insert_at (struct hash_table *ht, const void *item, const void *slot)
     
    203295    {
    204296      hash_rehash (ht);
     297#ifdef CONFIG_WITH_STRCACHE2
     298      if (ht->ht_strcache)
     299        return (void *)hash_find_slot_strcached (ht, item);
     300#endif /* CONFIG_WITH_STRCACHE2 */
    205301      return (void *) hash_find_slot (ht, item);
    206302    }
     
    215311  return hash_delete_at (ht, slot);
    216312}
     313
     314#ifdef CONFIG_WITH_STRCACHE2
     315void *
     316hash_delete_strcached (struct hash_table *ht, const void *item)
     317{
     318  void **slot = hash_find_slot_strcached (ht, item);
     319  return hash_delete_at (ht, slot);
     320}
     321#endif /* CONFIG_WITH_STRCACHE2 */
    217322
    218323void *
     
    353458  ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size);
    354459
     460#ifndef CONFIG_WITH_STRCACHE2
    355461  for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
    356462    {
     
    361467        }
    362468    }
     469#else  /* CONFIG_WITH_STRCACHE2 */
     470  if (ht->ht_strcache)
     471    for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
     472      {
     473        if (! HASH_VACANT (*ovp))
     474          {
     475            void **slot = hash_find_slot_strcached (ht, *ovp);
     476            *slot = *ovp;
     477          }
     478      }
     479  else
     480    for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
     481      {
     482        if (! HASH_VACANT (*ovp))
     483          {
     484            void **slot = hash_find_slot (ht, *ovp);
     485            *slot = *ovp;
     486          }
     487      }
     488#endif /* CONFIG_WITH_STRCACHE2 */
    363489  ht->ht_empty_slots = ht->ht_size - ht->ht_fill;
    364490  free (old_vec);
Note: See TracChangeset for help on using the changeset viewer.