hashtable.cpp 12.6 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25
#include "precompiled.hpp"
26 27
#include "classfile/altHashing.hpp"
#include "classfile/javaClasses.hpp"
28
#include "memory/allocation.inline.hpp"
29
#include "memory/filemap.hpp"
30 31 32 33 34 35
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/hashtable.inline.hpp"
36
#include "utilities/numberSeq.hpp"
D
duke 已提交
37

38

D
duke 已提交
39 40 41 42 43 44 45 46
// This is a generic hashtable, designed to be used for the symbol
// and string tables.
//
// It is implemented as an open hash table with a fixed number of buckets.
//
// %note:
//  - HashtableEntrys are allocated in blocks to reduce the space overhead.

Z
zgu 已提交
47 48
template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
  BasicHashtableEntry<F>* entry;
D
duke 已提交
49 50 51 52 53

  if (_free_list) {
    entry = _free_list;
    _free_list = _free_list->next();
  } else {
J
jrose 已提交
54 55
    if (_first_free_entry + _entry_size >= _end_block) {
      int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
D
duke 已提交
56
      int len = _entry_size * block_size;
J
jrose 已提交
57 58
      len = 1 << log2_intptr(len); // round down to power of 2
      assert(len >= _entry_size, "");
Z
zgu 已提交
59
      _first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
D
duke 已提交
60 61
      _end_block = _first_free_entry + len;
    }
Z
zgu 已提交
62
    entry = (BasicHashtableEntry<F>*)_first_free_entry;
D
duke 已提交
63 64 65
    _first_free_entry += _entry_size;
  }

J
jrose 已提交
66
  assert(_entry_size % HeapWordSize == 0, "");
D
duke 已提交
67 68 69 70 71
  entry->set_hash(hashValue);
  return entry;
}


Z
zgu 已提交
72 73
template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::new_entry(unsigned int hashValue, T obj) {
  HashtableEntry<T, F>* entry;
D
duke 已提交
74

Z
zgu 已提交
75
  entry = (HashtableEntry<T, F>*)BasicHashtable<F>::new_entry(hashValue);
76
  entry->set_literal(obj);
D
duke 已提交
77 78 79
  return entry;
}

80 81 82 83 84 85
// Check to see if the hashtable is unbalanced.  The caller set a flag to
// rehash at the next safepoint.  If this bucket is 60 times greater than the
// expected average bucket length, it's an unbalanced hashtable.
// This is somewhat an arbitrary heuristic but if one bucket gets to
// rehash_count which is currently 100, there's probably something wrong.

Z
zgu 已提交
86
template <MEMFLAGS F> bool BasicHashtable<F>::check_rehash_table(int count) {
87 88 89 90 91 92 93 94 95
  assert(table_size() != 0, "underflow");
  if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
    // Set a flag for the next safepoint, which should be at some guaranteed
    // safepoint interval.
    return true;
  }
  return false;
}

96 97
template <class T, MEMFLAGS F> jint Hashtable<T, F>::_seed = 0;

98 99 100 101
// Create a new table and using alternate hash code, populate the new table
// with the existing elements.   This can be used to change the hash code
// and could in the future change the size of the table.

Z
zgu 已提交
102
template <class T, MEMFLAGS F> void Hashtable<T, F>::move_to(Hashtable<T, F>* new_table) {
103 104 105 106 107 108

  // Initialize the global seed for hashing.
  _seed = AltHashing::compute_seed();
  assert(seed() != 0, "shouldn't be zero");

  int saved_entry_count = this->number_of_entries();
109 110 111

  // Iterate through the table and create a new entry for the new table
  for (int i = 0; i < new_table->table_size(); ++i) {
Z
zgu 已提交
112 113
    for (HashtableEntry<T, F>* p = bucket(i); p != NULL; ) {
      HashtableEntry<T, F>* next = p->next();
114 115
      T string = p->literal();
      // Use alternate hashing algorithm on the symbol in the first table
116
      unsigned int hashValue = string->new_hash(seed());
117 118 119
      // Get a new index relative to the new table (can also change size)
      int index = new_table->hash_to_index(hashValue);
      p->set_hash(hashValue);
120 121 122 123 124
      // Keep the shared bit in the Hashtable entry to indicate that this entry
      // can't be deleted.   The shared bit is the LSB in the _next field so
      // walking the hashtable past these entries requires
      // BasicHashtableEntry::make_ptr() call.
      bool keep_shared = p->is_shared();
125
      this->unlink_entry(p);
126
      new_table->add_entry(index, p);
127 128 129
      if (keep_shared) {
        p->set_shared();
      }
130 131 132 133 134 135 136 137 138 139 140
      p = next;
    }
  }
  // give the new table the free list as well
  new_table->copy_freelist(this);
  assert(new_table->number_of_entries() == saved_entry_count, "lost entry on dictionary copy?");

  // Destroy memory used by the buckets in the hashtable.  The memory
  // for the elements has been used in a new table and is not
  // destroyed.  The memory reuse will benefit resizing the SystemDictionary
  // to avoid a memory allocation spike at safepoint.
Z
zgu 已提交
141
  BasicHashtable<F>::free_buckets();
142 143
}

Z
zgu 已提交
144
template <MEMFLAGS F> void BasicHashtable<F>::free_buckets() {
145 146 147 148 149
  if (NULL != _buckets) {
    // Don't delete the buckets in the shared space.  They aren't
    // allocated by os::malloc
    if (!UseSharedSpaces ||
        !FileMapInfo::current_info()->is_in_shared_space(_buckets)) {
Z
zgu 已提交
150
       FREE_C_HEAP_ARRAY(HashtableBucket, _buckets, F);
151 152 153 154 155 156
    }
    _buckets = NULL;
  }
}


D
duke 已提交
157 158
// Reverse the order of elements in the hash buckets.

Z
zgu 已提交
159
template <MEMFLAGS F> void BasicHashtable<F>::reverse() {
D
duke 已提交
160 161

  for (int i = 0; i < _table_size; ++i) {
Z
zgu 已提交
162 163
    BasicHashtableEntry<F>* new_list = NULL;
    BasicHashtableEntry<F>* p = bucket(i);
D
duke 已提交
164
    while (p != NULL) {
Z
zgu 已提交
165
      BasicHashtableEntry<F>* next = p->next();
D
duke 已提交
166 167 168 169 170 171 172 173 174 175 176
      p->set_next(new_list);
      new_list = p;
      p = next;
    }
    *bucket_addr(i) = new_list;
  }
}


// Copy the table to the shared space.

Z
zgu 已提交
177
template <MEMFLAGS F> void BasicHashtable<F>::copy_table(char** top, char* end) {
D
duke 已提交
178 179 180 181 182 183 184 185

  // Dump the hash table entries.

  intptr_t *plen = (intptr_t*)(*top);
  *top += sizeof(*plen);

  int i;
  for (i = 0; i < _table_size; ++i) {
Z
zgu 已提交
186
    for (BasicHashtableEntry<F>** p = _buckets[i].entry_addr();
D
duke 已提交
187 188 189
                              *p != NULL;
                               p = (*p)->next_addr()) {
      if (*top + entry_size() > end) {
190
        report_out_of_shared_space(SharedMiscData);
D
duke 已提交
191
      }
Z
zgu 已提交
192
      *p = (BasicHashtableEntry<F>*)memcpy(*top, *p, entry_size());
D
duke 已提交
193 194 195 196 197 198 199 200
      *top += entry_size();
    }
  }
  *plen = (char*)(*top) - (char*)plen - sizeof(*plen);

  // Set the shared bit.

  for (i = 0; i < _table_size; ++i) {
Z
zgu 已提交
201
    for (BasicHashtableEntry<F>* p = bucket(i); p != NULL; p = p->next()) {
D
duke 已提交
202 203 204 205 206 207 208 209 210
      p->set_shared();
    }
  }
}



// Reverse the order of elements in the hash buckets.

Z
zgu 已提交
211
template <class T, MEMFLAGS F> void Hashtable<T, F>::reverse(void* boundary) {
D
duke 已提交
212

Z
zgu 已提交
213 214 215 216 217
  for (int i = 0; i < this->table_size(); ++i) {
    HashtableEntry<T, F>* high_list = NULL;
    HashtableEntry<T, F>* low_list = NULL;
    HashtableEntry<T, F>* last_low_entry = NULL;
    HashtableEntry<T, F>* p = bucket(i);
D
duke 已提交
218
    while (p != NULL) {
Z
zgu 已提交
219
      HashtableEntry<T, F>* next = p->next();
D
duke 已提交
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
      if ((void*)p->literal() >= boundary) {
        p->set_next(high_list);
        high_list = p;
      } else {
        p->set_next(low_list);
        low_list = p;
        if (last_low_entry == NULL) {
          last_low_entry = p;
        }
      }
      p = next;
    }
    if (low_list != NULL) {
      *bucket_addr(i) = low_list;
      last_low_entry->set_next(high_list);
    } else {
      *bucket_addr(i) = high_list;
    }
  }
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(Symbol *symbol) {
  return symbol->size() * HeapWordSize;
}

template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(oop oop) {
  // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
  // and the String.value array is shared by several Strings. However, starting from JDK8,
  // the String.value array is not shared anymore.
  assert(oop != NULL && oop->klass() == SystemDictionary::String_klass(), "only strings are supported");
  return (oop->size() + java_lang_String::value(oop)->size()) * HeapWordSize;
}

// Dump footprint and bucket length statistics
//
// Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
// add a new function Hashtable<T, F>::literal_size(MyNewType lit)

template <class T, MEMFLAGS F> void Hashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
  NumberSeq summary;
  int literal_bytes = 0;
  for (int i = 0; i < this->table_size(); ++i) {
    int count = 0;
    for (HashtableEntry<T, F>* e = bucket(i);
       e != NULL; e = e->next()) {
      count++;
      literal_bytes += literal_size(e->literal());
    }
    summary.add((double)count);
  }
  double num_buckets = summary.num();
  double num_entries = summary.sum();

  int bucket_bytes = (int)num_buckets * sizeof(bucket(0));
  int entry_bytes  = (int)num_entries * sizeof(HashtableEntry<T, F>);
  int total_bytes = literal_bytes +  bucket_bytes + entry_bytes;

  double bucket_avg  = (num_buckets <= 0) ? 0 : (bucket_bytes  / num_buckets);
  double entry_avg   = (num_entries <= 0) ? 0 : (entry_bytes   / num_entries);
  double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries);

  st->print_cr("%s statistics:", table_name);
  st->print_cr("Number of buckets       : %9d = %9d bytes, avg %7.3f", (int)num_buckets, bucket_bytes,  bucket_avg);
  st->print_cr("Number of entries       : %9d = %9d bytes, avg %7.3f", (int)num_entries, entry_bytes,   entry_avg);
  st->print_cr("Number of literals      : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg);
  st->print_cr("Total footprint         : %9s = %9d bytes", "", total_bytes);
  st->print_cr("Average bucket size     : %9.3f", summary.avg());
  st->print_cr("Variance of bucket size : %9.3f", summary.variance());
  st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd());
  st->print_cr("Maximum bucket size     : %9d", (int)summary.maximum());
}

D
duke 已提交
292 293 294

// Dump the hash table buckets.

Z
zgu 已提交
295 296
template <MEMFLAGS F> void BasicHashtable<F>::copy_buckets(char** top, char* end) {
  intptr_t len = _table_size * sizeof(HashtableBucket<F>);
D
duke 已提交
297 298 299 300 301 302 303
  *(intptr_t*)(*top) = len;
  *top += sizeof(intptr_t);

  *(intptr_t*)(*top) = _number_of_entries;
  *top += sizeof(intptr_t);

  if (*top + len > end) {
304
    report_out_of_shared_space(SharedMiscData);
D
duke 已提交
305
  }
Z
zgu 已提交
306
  _buckets = (HashtableBucket<F>*)memcpy(*top, _buckets, len);
D
duke 已提交
307 308 309 310 311 312
  *top += len;
}


#ifndef PRODUCT

Z
zgu 已提交
313
template <class T, MEMFLAGS F> void Hashtable<T, F>::print() {
D
duke 已提交
314 315
  ResourceMark rm;

Z
zgu 已提交
316 317
  for (int i = 0; i < BasicHashtable<F>::table_size(); i++) {
    HashtableEntry<T, F>* entry = bucket(i);
D
duke 已提交
318 319 320 321 322 323 324 325 326 327
    while(entry != NULL) {
      tty->print("%d : ", i);
      entry->literal()->print();
      tty->cr();
      entry = entry->next();
    }
  }
}


Z
zgu 已提交
328
template <MEMFLAGS F> void BasicHashtable<F>::verify() {
D
duke 已提交
329 330
  int count = 0;
  for (int i = 0; i < table_size(); i++) {
Z
zgu 已提交
331
    for (BasicHashtableEntry<F>* p = bucket(i); p != NULL; p = p->next()) {
D
duke 已提交
332 333 334 335 336 337 338 339 340 341 342 343
      ++count;
    }
  }
  assert(count == number_of_entries(), "number of hashtable entries incorrect");
}


#endif // PRODUCT


#ifdef ASSERT

Z
zgu 已提交
344
template <MEMFLAGS F> void BasicHashtable<F>::verify_lookup_length(double load) {
D
duke 已提交
345 346 347 348 349 350 351 352 353
  if ((double)_lookup_length / (double)_lookup_count > load * 2.0) {
    warning("Performance bug: SystemDictionary lookup_count=%d "
            "lookup_length=%d average=%lf load=%f",
            _lookup_count, _lookup_length,
            (double) _lookup_length / _lookup_count, load);
  }
}

#endif
354
// Explicitly instantiate these types
355
template class Hashtable<ConstantPool*, mtClass>;
Z
zgu 已提交
356
template class Hashtable<Symbol*, mtSymbol>;
357
template class Hashtable<Klass*, mtClass>;
Z
zgu 已提交
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
template class Hashtable<oop, mtClass>;
#ifdef SOLARIS
template class Hashtable<oop, mtSymbol>;
#endif
template class Hashtable<oopDesc*, mtSymbol>;
template class Hashtable<Symbol*, mtClass>;
template class HashtableEntry<Symbol*, mtSymbol>;
template class HashtableEntry<Symbol*, mtClass>;
template class HashtableEntry<oop, mtSymbol>;
template class BasicHashtableEntry<mtSymbol>;
template class BasicHashtableEntry<mtCode>;
template class BasicHashtable<mtClass>;
template class BasicHashtable<mtSymbol>;
template class BasicHashtable<mtCode>;
template class BasicHashtable<mtInternal>;