src/share/vm/utilities/hashtable.cpp

Mon, 03 Jan 2011 14:09:11 -0500

author
coleenp
date
Mon, 03 Jan 2011 14:09:11 -0500
changeset 2418
36c186bcc085
parent 2314
f95d63e2154a
child 2497
3582bf76420e
permissions
-rw-r--r--

6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places.
Summary: enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error.
Reviewed-by: kvn, kamg

duke@435 1 /*
stefank@2314 2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "memory/allocation.inline.hpp"
stefank@2314 27 #include "memory/resourceArea.hpp"
stefank@2314 28 #include "oops/oop.inline.hpp"
stefank@2314 29 #include "runtime/safepoint.hpp"
stefank@2314 30 #include "utilities/dtrace.hpp"
stefank@2314 31 #include "utilities/hashtable.hpp"
stefank@2314 32 #include "utilities/hashtable.inline.hpp"
duke@435 33
duke@435 34 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry,
duke@435 35 void*, unsigned int, oop, void*);
duke@435 36
duke@435 37 // This is a generic hashtable, designed to be used for the symbol
duke@435 38 // and string tables.
duke@435 39 //
duke@435 40 // It is implemented as an open hash table with a fixed number of buckets.
duke@435 41 //
duke@435 42 // %note:
duke@435 43 // - HashtableEntrys are allocated in blocks to reduce the space overhead.
duke@435 44
duke@435 45 BasicHashtableEntry* BasicHashtable::new_entry(unsigned int hashValue) {
duke@435 46 BasicHashtableEntry* entry;
duke@435 47
duke@435 48 if (_free_list) {
duke@435 49 entry = _free_list;
duke@435 50 _free_list = _free_list->next();
duke@435 51 } else {
jrose@867 52 if (_first_free_entry + _entry_size >= _end_block) {
jrose@867 53 int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
duke@435 54 int len = _entry_size * block_size;
jrose@867 55 len = 1 << log2_intptr(len); // round down to power of 2
jrose@867 56 assert(len >= _entry_size, "");
duke@435 57 _first_free_entry = NEW_C_HEAP_ARRAY(char, len);
duke@435 58 _end_block = _first_free_entry + len;
duke@435 59 }
duke@435 60 entry = (BasicHashtableEntry*)_first_free_entry;
duke@435 61 _first_free_entry += _entry_size;
duke@435 62 }
duke@435 63
jrose@867 64 assert(_entry_size % HeapWordSize == 0, "");
duke@435 65 entry->set_hash(hashValue);
duke@435 66 return entry;
duke@435 67 }
duke@435 68
duke@435 69
duke@435 70 HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) {
duke@435 71 HashtableEntry* entry;
duke@435 72
duke@435 73 entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue);
duke@435 74 entry->set_literal(obj); // clears literal string field
duke@435 75 HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
duke@435 76 this, hashValue, obj, entry);
duke@435 77 return entry;
duke@435 78 }
duke@435 79
duke@435 80
duke@435 81 // GC support
duke@435 82
duke@435 83 void Hashtable::unlink(BoolObjectClosure* is_alive) {
duke@435 84 // Readers of the table are unlocked, so we should only be removing
duke@435 85 // entries at a safepoint.
duke@435 86 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
duke@435 87 for (int i = 0; i < table_size(); ++i) {
duke@435 88 for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) {
duke@435 89 HashtableEntry* entry = *p;
duke@435 90 if (entry->is_shared()) {
duke@435 91 break;
duke@435 92 }
duke@435 93 assert(entry->literal() != NULL, "just checking");
duke@435 94 if (is_alive->do_object_b(entry->literal())) {
duke@435 95 p = entry->next_addr();
duke@435 96 } else {
duke@435 97 *p = entry->next();
duke@435 98 free_entry(entry);
duke@435 99 }
duke@435 100 }
duke@435 101 }
duke@435 102 }
duke@435 103
duke@435 104
duke@435 105 void Hashtable::oops_do(OopClosure* f) {
duke@435 106 for (int i = 0; i < table_size(); ++i) {
duke@435 107 HashtableEntry** p = bucket_addr(i);
duke@435 108 HashtableEntry* entry = bucket(i);
duke@435 109 while (entry != NULL) {
duke@435 110 f->do_oop(entry->literal_addr());
duke@435 111
duke@435 112 // Did the closure remove the literal from the table?
duke@435 113 if (entry->literal() == NULL) {
duke@435 114 assert(!entry->is_shared(), "immutable hashtable entry?");
duke@435 115 *p = entry->next();
duke@435 116 free_entry(entry);
duke@435 117 } else {
duke@435 118 p = entry->next_addr();
duke@435 119 }
duke@435 120 entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
duke@435 121 }
duke@435 122 }
duke@435 123 }
duke@435 124
duke@435 125
duke@435 126 // Reverse the order of elements in the hash buckets.
duke@435 127
duke@435 128 void BasicHashtable::reverse() {
duke@435 129
duke@435 130 for (int i = 0; i < _table_size; ++i) {
duke@435 131 BasicHashtableEntry* new_list = NULL;
duke@435 132 BasicHashtableEntry* p = bucket(i);
duke@435 133 while (p != NULL) {
duke@435 134 BasicHashtableEntry* next = p->next();
duke@435 135 p->set_next(new_list);
duke@435 136 new_list = p;
duke@435 137 p = next;
duke@435 138 }
duke@435 139 *bucket_addr(i) = new_list;
duke@435 140 }
duke@435 141 }
duke@435 142
duke@435 143
duke@435 144 // Copy the table to the shared space.
duke@435 145
duke@435 146 void BasicHashtable::copy_table(char** top, char* end) {
duke@435 147
duke@435 148 // Dump the hash table entries.
duke@435 149
duke@435 150 intptr_t *plen = (intptr_t*)(*top);
duke@435 151 *top += sizeof(*plen);
duke@435 152
duke@435 153 int i;
duke@435 154 for (i = 0; i < _table_size; ++i) {
duke@435 155 for (BasicHashtableEntry** p = _buckets[i].entry_addr();
duke@435 156 *p != NULL;
duke@435 157 p = (*p)->next_addr()) {
duke@435 158 if (*top + entry_size() > end) {
duke@435 159 warning("\nThe shared miscellaneous data space is not large "
duke@435 160 "enough to \npreload requested classes. Use "
duke@435 161 "-XX:SharedMiscDataSize= to increase \nthe initial "
duke@435 162 "size of the miscellaneous data space.\n");
duke@435 163 exit(2);
duke@435 164 }
duke@435 165 *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size());
duke@435 166 *top += entry_size();
duke@435 167 }
duke@435 168 }
duke@435 169 *plen = (char*)(*top) - (char*)plen - sizeof(*plen);
duke@435 170
duke@435 171 // Set the shared bit.
duke@435 172
duke@435 173 for (i = 0; i < _table_size; ++i) {
duke@435 174 for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
duke@435 175 p->set_shared();
duke@435 176 }
duke@435 177 }
duke@435 178 }
duke@435 179
duke@435 180
duke@435 181
duke@435 182 // Reverse the order of elements in the hash buckets.
duke@435 183
duke@435 184 void Hashtable::reverse(void* boundary) {
duke@435 185
duke@435 186 for (int i = 0; i < table_size(); ++i) {
duke@435 187 HashtableEntry* high_list = NULL;
duke@435 188 HashtableEntry* low_list = NULL;
duke@435 189 HashtableEntry* last_low_entry = NULL;
duke@435 190 HashtableEntry* p = bucket(i);
duke@435 191 while (p != NULL) {
duke@435 192 HashtableEntry* next = p->next();
duke@435 193 if ((void*)p->literal() >= boundary) {
duke@435 194 p->set_next(high_list);
duke@435 195 high_list = p;
duke@435 196 } else {
duke@435 197 p->set_next(low_list);
duke@435 198 low_list = p;
duke@435 199 if (last_low_entry == NULL) {
duke@435 200 last_low_entry = p;
duke@435 201 }
duke@435 202 }
duke@435 203 p = next;
duke@435 204 }
duke@435 205 if (low_list != NULL) {
duke@435 206 *bucket_addr(i) = low_list;
duke@435 207 last_low_entry->set_next(high_list);
duke@435 208 } else {
duke@435 209 *bucket_addr(i) = high_list;
duke@435 210 }
duke@435 211 }
duke@435 212 }
duke@435 213
duke@435 214
duke@435 215 // Dump the hash table buckets.
duke@435 216
duke@435 217 void BasicHashtable::copy_buckets(char** top, char* end) {
duke@435 218 intptr_t len = _table_size * sizeof(HashtableBucket);
duke@435 219 *(intptr_t*)(*top) = len;
duke@435 220 *top += sizeof(intptr_t);
duke@435 221
duke@435 222 *(intptr_t*)(*top) = _number_of_entries;
duke@435 223 *top += sizeof(intptr_t);
duke@435 224
duke@435 225 if (*top + len > end) {
duke@435 226 warning("\nThe shared miscellaneous data space is not large "
duke@435 227 "enough to \npreload requested classes. Use "
duke@435 228 "-XX:SharedMiscDataSize= to increase \nthe initial "
duke@435 229 "size of the miscellaneous data space.\n");
duke@435 230 exit(2);
duke@435 231 }
duke@435 232 _buckets = (HashtableBucket*)memcpy(*top, _buckets, len);
duke@435 233 *top += len;
duke@435 234 }
duke@435 235
duke@435 236
duke@435 237 #ifndef PRODUCT
duke@435 238
duke@435 239 void Hashtable::print() {
duke@435 240 ResourceMark rm;
duke@435 241
duke@435 242 for (int i = 0; i < table_size(); i++) {
duke@435 243 HashtableEntry* entry = bucket(i);
duke@435 244 while(entry != NULL) {
duke@435 245 tty->print("%d : ", i);
duke@435 246 entry->literal()->print();
duke@435 247 tty->cr();
duke@435 248 entry = entry->next();
duke@435 249 }
duke@435 250 }
duke@435 251 }
duke@435 252
duke@435 253
duke@435 254 void BasicHashtable::verify() {
duke@435 255 int count = 0;
duke@435 256 for (int i = 0; i < table_size(); i++) {
duke@435 257 for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
duke@435 258 ++count;
duke@435 259 }
duke@435 260 }
duke@435 261 assert(count == number_of_entries(), "number of hashtable entries incorrect");
duke@435 262 }
duke@435 263
duke@435 264
duke@435 265 #endif // PRODUCT
duke@435 266
duke@435 267
duke@435 268 #ifdef ASSERT
duke@435 269
duke@435 270 void BasicHashtable::verify_lookup_length(double load) {
duke@435 271 if ((double)_lookup_length / (double)_lookup_count > load * 2.0) {
duke@435 272 warning("Performance bug: SystemDictionary lookup_count=%d "
duke@435 273 "lookup_length=%d average=%lf load=%f",
duke@435 274 _lookup_count, _lookup_length,
duke@435 275 (double) _lookup_length / _lookup_count, load);
duke@435 276 }
duke@435 277 }
duke@435 278
duke@435 279 #endif

mercurial