| 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 |  | 
|---|