| 1 | /* |
| 2 | * Copyright (c) 2003, 2019, 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 | #ifndef SHARE_CLASSFILE_PLACEHOLDERS_HPP |
| 26 | #define SHARE_CLASSFILE_PLACEHOLDERS_HPP |
| 27 | |
| 28 | #include "runtime/thread.hpp" |
| 29 | #include "utilities/hashtable.hpp" |
| 30 | |
| 31 | class PlaceholderEntry; |
| 32 | |
| 33 | // Placeholder objects. These represent classes currently |
| 34 | // being loaded, as well as arrays of primitives. |
| 35 | // |
| 36 | |
| 37 | class PlaceholderTable : public Hashtable<Symbol*, mtClass> { |
| 38 | |
| 39 | public: |
| 40 | PlaceholderTable(int table_size); |
| 41 | |
| 42 | PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, bool havesupername, Symbol* supername); |
| 43 | void free_entry(PlaceholderEntry* entry); |
| 44 | |
| 45 | PlaceholderEntry* bucket(int i) const { |
| 46 | return (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::bucket(i); |
| 47 | } |
| 48 | |
| 49 | PlaceholderEntry** bucket_addr(int i) { |
| 50 | return (PlaceholderEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i); |
| 51 | } |
| 52 | |
| 53 | void add_entry(int index, PlaceholderEntry* new_entry) { |
| 54 | Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry); |
| 55 | } |
| 56 | |
| 57 | void add_entry(int index, unsigned int hash, Symbol* name, |
| 58 | ClassLoaderData* loader_data, bool havesupername, Symbol* supername); |
| 59 | |
| 60 | // This returns a Symbol* to match type for SystemDictionary |
| 61 | Symbol* find_entry(int index, unsigned int hash, |
| 62 | Symbol* name, ClassLoaderData* loader_data); |
| 63 | |
| 64 | PlaceholderEntry* get_entry(int index, unsigned int hash, |
| 65 | Symbol* name, ClassLoaderData* loader_data); |
| 66 | |
| 67 | // caller to create a placeholder entry must enumerate an action |
| 68 | // caller claims ownership of that action |
| 69 | // For parallel classloading: |
| 70 | // multiple LOAD_INSTANCE threads can proceed in parallel |
| 71 | // multiple LOAD_SUPER threads can proceed in parallel |
| 72 | // LOAD_SUPER needed to check for class circularity |
| 73 | // DEFINE_CLASS: ultimately define class must be single threaded |
| 74 | // on a class/classloader basis |
| 75 | // so the head of that queue owns the token |
| 76 | // and the rest of the threads return the result the first thread gets |
| 77 | enum classloadAction { |
| 78 | LOAD_INSTANCE = 1, // calling load_instance_class |
| 79 | LOAD_SUPER = 2, // loading superclass for this class |
| 80 | DEFINE_CLASS = 3 // find_or_define class |
| 81 | }; |
| 82 | |
| 83 | // find_and_add returns probe pointer - old or new |
| 84 | // If no entry exists, add a placeholder entry and push SeenThread for classloadAction |
| 85 | // If entry exists, reuse entry and push SeenThread for classloadAction |
| 86 | PlaceholderEntry* find_and_add(int index, unsigned int hash, |
| 87 | Symbol* name, ClassLoaderData* loader_data, |
| 88 | classloadAction action, Symbol* supername, |
| 89 | Thread* thread); |
| 90 | |
| 91 | void remove_entry(int index, unsigned int hash, |
| 92 | Symbol* name, ClassLoaderData* loader_data); |
| 93 | |
| 94 | // find_and_remove first removes SeenThread for classloadAction |
| 95 | // If all queues are empty and definer is null, remove the PlacheholderEntry completely |
| 96 | void find_and_remove(int index, unsigned int hash, |
| 97 | Symbol* name, ClassLoaderData* loader_data, |
| 98 | classloadAction action, Thread* thread); |
| 99 | |
| 100 | void print_on(outputStream* st) const; |
| 101 | void verify(); |
| 102 | }; |
| 103 | |
| 104 | // SeenThread objects represent list of threads that are |
| 105 | // currently performing a load action on a class. |
| 106 | // For class circularity, set before loading a superclass. |
| 107 | // For bootclasssearchpath, set before calling load_instance_class. |
| 108 | // Defining must be single threaded on a class/classloader basis |
| 109 | // For DEFINE_CLASS, the head of the queue owns the |
| 110 | // define token and the rest of the threads wait to return the |
| 111 | // result the first thread gets. |
| 112 | class SeenThread: public CHeapObj<mtInternal> { |
| 113 | private: |
| 114 | Thread *_thread; |
| 115 | SeenThread* _stnext; |
| 116 | SeenThread* _stprev; |
| 117 | public: |
| 118 | SeenThread(Thread *thread) { |
| 119 | _thread = thread; |
| 120 | _stnext = NULL; |
| 121 | _stprev = NULL; |
| 122 | } |
| 123 | Thread* thread() const { return _thread;} |
| 124 | void set_thread(Thread *thread) { _thread = thread; } |
| 125 | |
| 126 | SeenThread* next() const { return _stnext;} |
| 127 | void set_next(SeenThread *seen) { _stnext = seen; } |
| 128 | void set_prev(SeenThread *seen) { _stprev = seen; } |
| 129 | |
| 130 | void print_action_queue(outputStream* st) { |
| 131 | SeenThread* seen = this; |
| 132 | while (seen != NULL) { |
| 133 | seen->thread()->print_value_on(st); |
| 134 | st->print(", " ); |
| 135 | seen = seen->next(); |
| 136 | } |
| 137 | } |
| 138 | }; |
| 139 | |
| 140 | // Placeholder objects represent classes currently being loaded. |
| 141 | // All threads examining the placeholder table must hold the |
| 142 | // SystemDictionary_lock, so we don't need special precautions |
| 143 | // on store ordering here. |
| 144 | // The system dictionary is the only user of this class. |
| 145 | |
| 146 | class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> { |
| 147 | |
| 148 | private: |
| 149 | ClassLoaderData* _loader_data; // initiating loader |
| 150 | bool _havesupername; // distinguish between null supername, and unknown |
| 151 | Symbol* _supername; |
| 152 | Thread* _definer; // owner of define token |
| 153 | InstanceKlass* _instanceKlass; // InstanceKlass from successful define |
| 154 | SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class |
| 155 | SeenThread* _loadInstanceThreadQ; // loadInstance thread |
| 156 | // can be multiple threads if classloader object lock broken by application |
| 157 | // or if classloader supports parallel classloading |
| 158 | |
| 159 | SeenThread* _defineThreadQ; // queue of Threads trying to define this class |
| 160 | // including _definer |
| 161 | // _definer owns token |
| 162 | // queue waits for and returns results from _definer |
| 163 | |
| 164 | public: |
| 165 | // Simple accessors, used only by SystemDictionary |
| 166 | Symbol* klassname() const { return literal(); } |
| 167 | |
| 168 | ClassLoaderData* loader_data() const { return _loader_data; } |
| 169 | void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; } |
| 170 | |
| 171 | bool havesupername() const { return _havesupername; } |
| 172 | void set_havesupername(bool havesupername) { _havesupername = havesupername; } |
| 173 | |
| 174 | Symbol* supername() const { return _supername; } |
| 175 | void set_supername(Symbol* supername) { |
| 176 | _supername = supername; |
| 177 | if (_supername != NULL) _supername->increment_refcount(); |
| 178 | } |
| 179 | |
| 180 | Thread* definer() const {return _definer; } |
| 181 | void set_definer(Thread* definer) { _definer = definer; } |
| 182 | |
| 183 | InstanceKlass* instance_klass() const {return _instanceKlass; } |
| 184 | void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; } |
| 185 | |
| 186 | SeenThread* superThreadQ() const { return _superThreadQ; } |
| 187 | void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; } |
| 188 | |
| 189 | SeenThread* loadInstanceThreadQ() const { return _loadInstanceThreadQ; } |
| 190 | void set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; } |
| 191 | |
| 192 | SeenThread* defineThreadQ() const { return _defineThreadQ; } |
| 193 | void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; } |
| 194 | |
| 195 | PlaceholderEntry* next() const { |
| 196 | return (PlaceholderEntry*)HashtableEntry<Symbol*, mtClass>::next(); |
| 197 | } |
| 198 | |
| 199 | PlaceholderEntry** next_addr() { |
| 200 | return (PlaceholderEntry**)HashtableEntry<Symbol*, mtClass>::next_addr(); |
| 201 | } |
| 202 | |
| 203 | // Test for equality |
| 204 | // Entries are unique for class/classloader name pair |
| 205 | bool equals(Symbol* class_name, ClassLoaderData* loader) const { |
| 206 | return (klassname() == class_name && loader_data() == loader); |
| 207 | } |
| 208 | |
| 209 | SeenThread* actionToQueue(PlaceholderTable::classloadAction action) { |
| 210 | SeenThread* queuehead = NULL; |
| 211 | switch (action) { |
| 212 | case PlaceholderTable::LOAD_INSTANCE: |
| 213 | queuehead = _loadInstanceThreadQ; |
| 214 | break; |
| 215 | case PlaceholderTable::LOAD_SUPER: |
| 216 | queuehead = _superThreadQ; |
| 217 | break; |
| 218 | case PlaceholderTable::DEFINE_CLASS: |
| 219 | queuehead = _defineThreadQ; |
| 220 | break; |
| 221 | default: Unimplemented(); |
| 222 | } |
| 223 | return queuehead; |
| 224 | } |
| 225 | |
| 226 | void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) { |
| 227 | switch (action) { |
| 228 | case PlaceholderTable::LOAD_INSTANCE: |
| 229 | _loadInstanceThreadQ = seenthread; |
| 230 | break; |
| 231 | case PlaceholderTable::LOAD_SUPER: |
| 232 | _superThreadQ = seenthread; |
| 233 | break; |
| 234 | case PlaceholderTable::DEFINE_CLASS: |
| 235 | _defineThreadQ = seenthread; |
| 236 | break; |
| 237 | default: Unimplemented(); |
| 238 | } |
| 239 | return; |
| 240 | } |
| 241 | |
| 242 | bool super_load_in_progress() { |
| 243 | return (_superThreadQ != NULL); |
| 244 | } |
| 245 | |
| 246 | bool instance_load_in_progress() { |
| 247 | return (_loadInstanceThreadQ != NULL); |
| 248 | } |
| 249 | |
| 250 | bool define_class_in_progress() { |
| 251 | return (_defineThreadQ != NULL); |
| 252 | } |
| 253 | |
| 254 | // Doubly-linked list of Threads per action for class/classloader pair |
| 255 | // Class circularity support: links in thread before loading superclass |
| 256 | // bootstrapsearchpath support: links in a thread before load_instance_class |
| 257 | // definers: use as queue of define requestors, including owner of |
| 258 | // define token. Appends for debugging of requestor order |
| 259 | void add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { |
| 260 | assert_lock_strong(SystemDictionary_lock); |
| 261 | SeenThread* threadEntry = new SeenThread(thread); |
| 262 | SeenThread* seen = actionToQueue(action); |
| 263 | |
| 264 | if (seen == NULL) { |
| 265 | set_threadQ(threadEntry, action); |
| 266 | return; |
| 267 | } |
| 268 | SeenThread* next; |
| 269 | while ((next = seen->next()) != NULL) { |
| 270 | seen = next; |
| 271 | } |
| 272 | seen->set_next(threadEntry); |
| 273 | threadEntry->set_prev(seen); |
| 274 | return; |
| 275 | } |
| 276 | |
| 277 | bool check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { |
| 278 | assert_lock_strong(SystemDictionary_lock); |
| 279 | SeenThread* threadQ = actionToQueue(action); |
| 280 | SeenThread* seen = threadQ; |
| 281 | while (seen) { |
| 282 | if (thread == seen->thread()) { |
| 283 | return true; |
| 284 | } |
| 285 | seen = seen->next(); |
| 286 | } |
| 287 | return false; |
| 288 | } |
| 289 | |
| 290 | // returns true if seenthreadQ is now empty |
| 291 | // Note, caller must ensure probe still exists while holding |
| 292 | // SystemDictionary_lock |
| 293 | // ignores if cleanup has already been done |
| 294 | // if found, deletes SeenThread |
| 295 | bool remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { |
| 296 | assert_lock_strong(SystemDictionary_lock); |
| 297 | SeenThread* threadQ = actionToQueue(action); |
| 298 | SeenThread* seen = threadQ; |
| 299 | SeenThread* prev = NULL; |
| 300 | while (seen) { |
| 301 | if (thread == seen->thread()) { |
| 302 | if (prev) { |
| 303 | prev->set_next(seen->next()); |
| 304 | } else { |
| 305 | set_threadQ(seen->next(), action); |
| 306 | } |
| 307 | if (seen->next()) { |
| 308 | seen->next()->set_prev(prev); |
| 309 | } |
| 310 | delete seen; |
| 311 | break; |
| 312 | } |
| 313 | prev = seen; |
| 314 | seen = seen->next(); |
| 315 | } |
| 316 | return (actionToQueue(action) == NULL); |
| 317 | } |
| 318 | |
| 319 | // Print method doesn't append a cr |
| 320 | void print_entry(outputStream* st) const; |
| 321 | void verify() const; |
| 322 | }; |
| 323 | |
| 324 | #endif // SHARE_CLASSFILE_PLACEHOLDERS_HPP |
| 325 | |