duke@435: /* acorn@4425: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP stefank@2314: #define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP stefank@2314: stefank@2325: #include "runtime/thread.hpp" stefank@2314: #include "utilities/hashtable.hpp" stefank@2314: duke@435: class PlaceholderEntry; duke@435: duke@435: // Placeholder objects. These represent classes currently duke@435: // being loaded, as well as arrays of primitives. duke@435: // duke@435: zgu@3900: class PlaceholderTable : public TwoOopHashtable { duke@435: friend class VMStructs; duke@435: duke@435: public: duke@435: PlaceholderTable(int table_size); duke@435: coleenp@4037: PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, bool havesupername, Symbol* supername); coleenp@2497: void free_entry(PlaceholderEntry* entry); duke@435: duke@435: PlaceholderEntry* bucket(int i) { zgu@3900: return (PlaceholderEntry*)Hashtable::bucket(i); duke@435: } duke@435: duke@435: PlaceholderEntry** bucket_addr(int i) { zgu@3900: return (PlaceholderEntry**)Hashtable::bucket_addr(i); duke@435: } duke@435: duke@435: void add_entry(int index, PlaceholderEntry* new_entry) { zgu@3900: Hashtable::add_entry(index, (HashtableEntry*)new_entry); duke@435: } duke@435: coleenp@2497: void add_entry(int index, unsigned int hash, Symbol* name, coleenp@4037: ClassLoaderData* loader_data, bool havesupername, Symbol* supername); duke@435: coleenp@2497: // This returns a Symbol* to match type for SystemDictionary coleenp@2497: Symbol* find_entry(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data); duke@435: duke@435: PlaceholderEntry* get_entry(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data); duke@435: duke@435: // caller to create a placeholder entry must enumerate an action duke@435: // caller claims ownership of that action duke@435: // For parallel classloading: duke@435: // multiple LOAD_INSTANCE threads can proceed in parallel duke@435: // multiple LOAD_SUPER threads can proceed in parallel duke@435: // LOAD_SUPER needed to check for class circularity duke@435: // DEFINE_CLASS: ultimately define class must be single threaded duke@435: // on a class/classloader basis duke@435: // so the head of that queue owns the token duke@435: // and the rest of the threads return the result the first thread gets duke@435: enum classloadAction { duke@435: LOAD_INSTANCE = 1, // calling load_instance_class duke@435: LOAD_SUPER = 2, // loading superclass for this class duke@435: DEFINE_CLASS = 3 // find_or_define class duke@435: }; duke@435: duke@435: // find_and_add returns probe pointer - old or new acorn@4425: // If no entry exists, add a placeholder entry and push SeenThread for classloadAction duke@435: // If entry exists, reuse entry and push SeenThread for classloadAction duke@435: PlaceholderEntry* find_and_add(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data, coleenp@2497: classloadAction action, Symbol* supername, duke@435: Thread* thread); duke@435: duke@435: void remove_entry(int index, unsigned int hash, coleenp@4037: Symbol* name, ClassLoaderData* loader_data); duke@435: acorn@4425: // find_and_remove first removes SeenThread for classloadAction acorn@4425: // If all queues are empty and definer is null, remove the PlacheholderEntry completely duke@435: void find_and_remove(int index, unsigned int hash, acorn@4425: Symbol* name, ClassLoaderData* loader_data, acorn@4425: classloadAction action, Thread* thread); duke@435: duke@435: // GC support. coleenp@4037: void classes_do(KlassClosure* f); duke@435: duke@435: // JVMTI support coleenp@4037: void entries_do(void f(Symbol*)); duke@435: duke@435: #ifndef PRODUCT duke@435: void print(); duke@435: #endif duke@435: void verify(); duke@435: }; duke@435: duke@435: // SeenThread objects represent list of threads that are duke@435: // currently performing a load action on a class. duke@435: // For class circularity, set before loading a superclass. duke@435: // For bootclasssearchpath, set before calling load_instance_class. duke@435: // Defining must be single threaded on a class/classloader basis duke@435: // For DEFINE_CLASS, the head of the queue owns the duke@435: // define token and the rest of the threads wait to return the duke@435: // result the first thread gets. zgu@3900: class SeenThread: public CHeapObj { duke@435: private: duke@435: Thread *_thread; duke@435: SeenThread* _stnext; duke@435: SeenThread* _stprev; duke@435: public: duke@435: SeenThread(Thread *thread) { duke@435: _thread = thread; duke@435: _stnext = NULL; duke@435: _stprev = NULL; duke@435: } duke@435: Thread* thread() const { return _thread;} duke@435: void set_thread(Thread *thread) { _thread = thread; } duke@435: duke@435: SeenThread* next() const { return _stnext;} duke@435: void set_next(SeenThread *seen) { _stnext = seen; } duke@435: void set_prev(SeenThread *seen) { _stprev = seen; } duke@435: duke@435: #ifndef PRODUCT duke@435: void printActionQ() { duke@435: SeenThread* seen = this; duke@435: while (seen != NULL) { duke@435: seen->thread()->print_value(); duke@435: tty->print(", "); duke@435: seen = seen->next(); duke@435: } duke@435: } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: // Placeholder objects represent classes currently being loaded. duke@435: // All threads examining the placeholder table must hold the duke@435: // SystemDictionary_lock, so we don't need special precautions duke@435: // on store ordering here. duke@435: // The system dictionary is the only user of this class. duke@435: zgu@3900: class PlaceholderEntry : public HashtableEntry { duke@435: friend class VMStructs; duke@435: duke@435: duke@435: private: coleenp@4037: ClassLoaderData* _loader_data; // initiating loader duke@435: bool _havesupername; // distinguish between null supername, and unknown coleenp@2497: Symbol* _supername; duke@435: Thread* _definer; // owner of define token coleenp@4037: Klass* _instanceKlass; // InstanceKlass from successful define duke@435: SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class duke@435: SeenThread* _loadInstanceThreadQ; // loadInstance thread duke@435: // can be multiple threads if classloader object lock broken by application duke@435: // or if classloader supports parallel classloading duke@435: duke@435: SeenThread* _defineThreadQ; // queue of Threads trying to define this class duke@435: // including _definer duke@435: // _definer owns token duke@435: // queue waits for and returns results from _definer duke@435: duke@435: public: duke@435: // Simple accessors, used only by SystemDictionary coleenp@2497: Symbol* klassname() const { return literal(); } duke@435: coleenp@4037: ClassLoaderData* loader_data() const { return _loader_data; } coleenp@4037: void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; } duke@435: duke@435: bool havesupername() const { return _havesupername; } duke@435: void set_havesupername(bool havesupername) { _havesupername = havesupername; } duke@435: coleenp@2497: Symbol* supername() const { return _supername; } coleenp@2497: void set_supername(Symbol* supername) { coleenp@2497: _supername = supername; coleenp@2497: if (_supername != NULL) _supername->increment_refcount(); coleenp@2497: } duke@435: duke@435: Thread* definer() const {return _definer; } duke@435: void set_definer(Thread* definer) { _definer = definer; } duke@435: hseigel@4278: Klass* instance_klass() const {return _instanceKlass; } hseigel@4278: void set_instance_klass(Klass* ik) { _instanceKlass = ik; } duke@435: duke@435: SeenThread* superThreadQ() const { return _superThreadQ; } duke@435: void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; } duke@435: duke@435: SeenThread* loadInstanceThreadQ() const { return _loadInstanceThreadQ; } duke@435: void set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; } duke@435: duke@435: SeenThread* defineThreadQ() const { return _defineThreadQ; } duke@435: void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; } duke@435: duke@435: PlaceholderEntry* next() const { zgu@3900: return (PlaceholderEntry*)HashtableEntry::next(); duke@435: } duke@435: duke@435: PlaceholderEntry** next_addr() { zgu@3900: return (PlaceholderEntry**)HashtableEntry::next_addr(); duke@435: } duke@435: duke@435: // Test for equality duke@435: // Entries are unique for class/classloader name pair coleenp@4037: bool equals(Symbol* class_name, ClassLoaderData* loader) const { coleenp@4037: return (klassname() == class_name && loader_data() == loader); duke@435: } duke@435: duke@435: SeenThread* actionToQueue(PlaceholderTable::classloadAction action) { duke@435: SeenThread* queuehead; duke@435: switch (action) { duke@435: case PlaceholderTable::LOAD_INSTANCE: duke@435: queuehead = _loadInstanceThreadQ; duke@435: break; duke@435: case PlaceholderTable::LOAD_SUPER: duke@435: queuehead = _superThreadQ; duke@435: break; duke@435: case PlaceholderTable::DEFINE_CLASS: duke@435: queuehead = _defineThreadQ; duke@435: break; duke@435: default: Unimplemented(); duke@435: } duke@435: return queuehead; duke@435: } duke@435: duke@435: void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) { duke@435: switch (action) { duke@435: case PlaceholderTable::LOAD_INSTANCE: duke@435: _loadInstanceThreadQ = seenthread; duke@435: break; duke@435: case PlaceholderTable::LOAD_SUPER: duke@435: _superThreadQ = seenthread; duke@435: break; duke@435: case PlaceholderTable::DEFINE_CLASS: duke@435: _defineThreadQ = seenthread; duke@435: break; duke@435: default: Unimplemented(); duke@435: } duke@435: return; duke@435: } duke@435: duke@435: bool super_load_in_progress() { duke@435: return (_superThreadQ != NULL); duke@435: } duke@435: duke@435: bool instance_load_in_progress() { duke@435: return (_loadInstanceThreadQ != NULL); duke@435: } duke@435: duke@435: bool define_class_in_progress() { duke@435: return (_defineThreadQ != NULL); duke@435: } duke@435: duke@435: // Doubly-linked list of Threads per action for class/classloader pair duke@435: // Class circularity support: links in thread before loading superclass duke@435: // bootstrapsearchpath support: links in a thread before load_instance_class duke@435: // definers: use as queue of define requestors, including owner of duke@435: // define token. Appends for debugging of requestor order duke@435: void add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { duke@435: assert_lock_strong(SystemDictionary_lock); duke@435: SeenThread* threadEntry = new SeenThread(thread); duke@435: SeenThread* seen = actionToQueue(action); duke@435: duke@435: if (seen == NULL) { duke@435: set_threadQ(threadEntry, action); duke@435: return; duke@435: } duke@435: SeenThread* next; duke@435: while ((next = seen->next()) != NULL) { duke@435: seen = next; duke@435: } duke@435: seen->set_next(threadEntry); duke@435: threadEntry->set_prev(seen); duke@435: return; duke@435: } duke@435: duke@435: bool check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { duke@435: assert_lock_strong(SystemDictionary_lock); duke@435: SeenThread* threadQ = actionToQueue(action); duke@435: SeenThread* seen = threadQ; duke@435: while (seen) { duke@435: if (thread == seen->thread()) { duke@435: return true; duke@435: } duke@435: seen = seen->next(); duke@435: } duke@435: return false; duke@435: } duke@435: duke@435: // returns true if seenthreadQ is now empty duke@435: // Note, caller must ensure probe still exists while holding duke@435: // SystemDictionary_lock duke@435: // ignores if cleanup has already been done duke@435: // if found, deletes SeenThread duke@435: bool remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { duke@435: assert_lock_strong(SystemDictionary_lock); duke@435: SeenThread* threadQ = actionToQueue(action); duke@435: SeenThread* seen = threadQ; duke@435: SeenThread* prev = NULL; duke@435: while (seen) { duke@435: if (thread == seen->thread()) { duke@435: if (prev) { duke@435: prev->set_next(seen->next()); duke@435: } else { duke@435: set_threadQ(seen->next(), action); duke@435: } duke@435: if (seen->next()) { duke@435: seen->next()->set_prev(prev); duke@435: } duke@435: delete seen; duke@435: break; duke@435: } duke@435: prev = seen; duke@435: seen = seen->next(); duke@435: } duke@435: return (actionToQueue(action) == NULL); duke@435: } duke@435: duke@435: // GC support duke@435: // Applies "f->do_oop" to all root oops in the placeholder table. coleenp@4037: void classes_do(KlassClosure* closure); duke@435: duke@435: // Print method doesn't append a cr duke@435: void print() const PRODUCT_RETURN; duke@435: void verify() const; duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP