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