placeholders.cpp revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25# include "incls/_precompiled.incl" 26# include "incls/_placeholders.cpp.incl" 27 28// Placeholder methods 29 30PlaceholderEntry* PlaceholderTable::new_entry(int hash, symbolOop name, 31 oop loader, bool havesupername, 32 symbolOop supername) { 33 PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable::new_entry(hash, name); 34 entry->set_loader(loader); 35 entry->set_havesupername(havesupername); 36 entry->set_supername(supername); 37 entry->set_superThreadQ(NULL); 38 entry->set_loadInstanceThreadQ(NULL); 39 entry->set_defineThreadQ(NULL); 40 entry->set_definer(NULL); 41 entry->set_instanceKlass(NULL); 42 return entry; 43} 44 45 46// Placeholder objects represent classes currently being loaded. 47// All threads examining the placeholder table must hold the 48// SystemDictionary_lock, so we don't need special precautions 49// on store ordering here. 50void PlaceholderTable::add_entry(int index, unsigned int hash, 51 symbolHandle class_name, Handle class_loader, 52 bool havesupername, symbolHandle supername){ 53 assert_locked_or_safepoint(SystemDictionary_lock); 54 assert(!class_name.is_null(), "adding NULL obj"); 55 56 // Both readers and writers are locked so it's safe to just 57 // create the placeholder and insert it in the list without a membar. 58 PlaceholderEntry* entry = new_entry(hash, class_name(), class_loader(), havesupername, supername()); 59 add_entry(index, entry); 60} 61 62 63// Remove a placeholder object. 64void PlaceholderTable::remove_entry(int index, unsigned int hash, 65 symbolHandle class_name, 66 Handle class_loader) { 67 assert_locked_or_safepoint(SystemDictionary_lock); 68 PlaceholderEntry** p = bucket_addr(index); 69 while (*p) { 70 PlaceholderEntry *probe = *p; 71 if (probe->hash() == hash && probe->equals(class_name(), class_loader())) { 72 // Delete entry 73 *p = probe->next(); 74 free_entry(probe); 75 return; 76 } 77 p = probe->next_addr(); 78 } 79} 80 81PlaceholderEntry* PlaceholderTable::get_entry(int index, unsigned int hash, 82 symbolHandle class_name, 83 Handle class_loader) { 84 assert_locked_or_safepoint(SystemDictionary_lock); 85 86 symbolOop class_name_ = class_name(); 87 oop class_loader_ = class_loader(); 88 89 for (PlaceholderEntry *place_probe = bucket(index); 90 place_probe != NULL; 91 place_probe = place_probe->next()) { 92 if (place_probe->hash() == hash && 93 place_probe->equals(class_name_, class_loader_)) { 94 return place_probe; 95 } 96 } 97 return NULL; 98} 99 100symbolOop PlaceholderTable::find_entry(int index, unsigned int hash, 101 symbolHandle class_name, 102 Handle class_loader) { 103 PlaceholderEntry* probe = get_entry(index, hash, class_name, class_loader); 104 return (probe? probe->klass(): symbolOop(NULL)); 105} 106 107 // find_and_add returns probe pointer - old or new 108 // If no entry exists, add a placeholder entry 109 // If entry exists, reuse entry 110 // For both, push SeenThread for classloadAction 111 // if havesupername: this is used for circularity for instanceklass loading 112PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, symbolHandle name, Handle loader, classloadAction action, symbolHandle supername, Thread* thread) { 113 PlaceholderEntry* probe = get_entry(index, hash, name, loader); 114 if (probe == NULL) { 115 // Nothing found, add place holder 116 add_entry(index, hash, name, loader, (action == LOAD_SUPER), supername); 117 probe = get_entry(index, hash, name, loader); 118 } else { 119 if (action == LOAD_SUPER) { 120 probe->set_havesupername(true); 121 probe->set_supername(supername()); 122 } 123 } 124 if (probe) probe->add_seen_thread(thread, action); 125 return probe; 126} 127 128 129// placeholder used to track class loading internal states 130// placeholder existence now for loading superclass/superinterface 131// superthreadQ tracks class circularity, while loading superclass/superinterface 132// loadInstanceThreadQ tracks load_instance_class calls 133// definer() tracks the single thread that owns define token 134// defineThreadQ tracks waiters on defining thread's results 135// 1st claimant creates placeholder 136// find_and_add adds SeenThread entry for appropriate queue 137// All claimants remove SeenThread after completing action 138// On removal: if definer and all queues empty, remove entry 139// Note: you can be in both placeholders and systemDictionary 140// see parse_stream for redefine classes 141// Therefore - must always check SD first 142// Ignores the case where entry is not found 143void PlaceholderTable::find_and_remove(int index, unsigned int hash, 144 symbolHandle name, Handle loader, Thread* thread) { 145 assert_locked_or_safepoint(SystemDictionary_lock); 146 PlaceholderEntry *probe = get_entry(index, hash, name, loader); 147 if (probe != NULL) { 148 // No other threads using this entry 149 if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL) 150 && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) { 151 remove_entry(index, hash, name, loader); 152 } 153 } 154 } 155 156PlaceholderTable::PlaceholderTable(int table_size) 157 : TwoOopHashtable(table_size, sizeof(PlaceholderEntry)) { 158} 159 160 161void PlaceholderTable::oops_do(OopClosure* f) { 162 for (int index = 0; index < table_size(); index++) { 163 for (PlaceholderEntry* probe = bucket(index); 164 probe != NULL; 165 probe = probe->next()) { 166 probe->oops_do(f); 167 } 168 } 169} 170 171 172void PlaceholderEntry::oops_do(OopClosure* blk) { 173 assert(klass() != NULL, "should have a non-null klass"); 174 blk->do_oop((oop*)klass_addr()); 175 if (_loader != NULL) { 176 blk->do_oop(loader_addr()); 177 } 178 if (_supername != NULL) { 179 blk->do_oop((oop*)supername_addr()); 180 } 181 if (_instanceKlass != NULL) { 182 blk->do_oop((oop*)instanceKlass_addr()); 183 } 184} 185 186// do all entries in the placeholder table 187void PlaceholderTable::entries_do(void f(symbolOop, oop)) { 188 for (int index = 0; index < table_size(); index++) { 189 for (PlaceholderEntry* probe = bucket(index); 190 probe != NULL; 191 probe = probe->next()) { 192 f(probe->klass(), probe->loader()); 193 } 194 } 195} 196 197 198#ifndef PRODUCT 199// Note, doesn't append a cr 200void PlaceholderEntry::print() const { 201 klass()->print_value(); 202 if (loader() != NULL) { 203 tty->print(", loader "); 204 loader()->print_value(); 205 } 206 if (supername() != NULL) { 207 tty->print(", supername "); 208 supername()->print_value(); 209 } 210 if (definer() != NULL) { 211 tty->print(", definer "); 212 definer()->print_value(); 213 } 214 if (instanceKlass() != NULL) { 215 tty->print(", instanceKlass "); 216 instanceKlass()->print_value(); 217 } 218 tty->print("\n"); 219 tty->print("loadInstanceThreadQ threads:"); 220 loadInstanceThreadQ()->printActionQ(); 221 tty->print("\n"); 222 tty->print("superThreadQ threads:"); 223 superThreadQ()->printActionQ(); 224 tty->print("\n"); 225 tty->print("defineThreadQ threads:"); 226 defineThreadQ()->printActionQ(); 227 tty->print("\n"); 228} 229#endif 230 231void PlaceholderEntry::verify() const { 232 guarantee(loader() == NULL || loader()->is_instance(), 233 "checking type of _loader"); 234 guarantee(instanceKlass() == NULL 235 || Klass::cast(instanceKlass())->oop_is_instance(), 236 "checking type of instanceKlass result"); 237 klass()->verify(); 238} 239 240void PlaceholderTable::verify() { 241 int element_count = 0; 242 for (int pindex = 0; pindex < table_size(); pindex++) { 243 for (PlaceholderEntry* probe = bucket(pindex); 244 probe != NULL; 245 probe = probe->next()) { 246 probe->verify(); 247 element_count++; // both klasses and place holders count 248 } 249 } 250 guarantee(number_of_entries() == element_count, 251 "Verify of system dictionary failed"); 252} 253 254 255#ifndef PRODUCT 256void PlaceholderTable::print() { 257 for (int pindex = 0; pindex < table_size(); pindex++) { 258 for (PlaceholderEntry* probe = bucket(pindex); 259 probe != NULL; 260 probe = probe->next()) { 261 if (Verbose) tty->print("%4d: ", pindex); 262 tty->print(" place holder "); 263 264 probe->print(); 265 tty->cr(); 266 } 267 } 268} 269#endif 270