Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/placeholders.hpp
32285 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP25#define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP2627#include "runtime/thread.hpp"28#include "utilities/hashtable.hpp"2930class PlaceholderEntry;3132// Placeholder objects. These represent classes currently33// being loaded, as well as arrays of primitives.34//3536class PlaceholderTable : public TwoOopHashtable<Symbol*, mtClass> {37friend class VMStructs;3839public:40PlaceholderTable(int table_size);4142PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, bool havesupername, Symbol* supername);43void free_entry(PlaceholderEntry* entry);4445PlaceholderEntry* bucket(int i) {46return (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::bucket(i);47}4849PlaceholderEntry** bucket_addr(int i) {50return (PlaceholderEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);51}5253void add_entry(int index, PlaceholderEntry* new_entry) {54Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);55}5657void add_entry(int index, unsigned int hash, Symbol* name,58ClassLoaderData* loader_data, bool havesupername, Symbol* supername);5960// This returns a Symbol* to match type for SystemDictionary61Symbol* find_entry(int index, unsigned int hash,62Symbol* name, ClassLoaderData* loader_data);6364PlaceholderEntry* get_entry(int index, unsigned int hash,65Symbol* name, ClassLoaderData* loader_data);6667// caller to create a placeholder entry must enumerate an action68// caller claims ownership of that action69// For parallel classloading:70// multiple LOAD_INSTANCE threads can proceed in parallel71// multiple LOAD_SUPER threads can proceed in parallel72// LOAD_SUPER needed to check for class circularity73// DEFINE_CLASS: ultimately define class must be single threaded74// on a class/classloader basis75// so the head of that queue owns the token76// and the rest of the threads return the result the first thread gets77enum classloadAction {78LOAD_INSTANCE = 1, // calling load_instance_class79LOAD_SUPER = 2, // loading superclass for this class80DEFINE_CLASS = 3 // find_or_define class81};8283// find_and_add returns probe pointer - old or new84// If no entry exists, add a placeholder entry and push SeenThread for classloadAction85// If entry exists, reuse entry and push SeenThread for classloadAction86PlaceholderEntry* find_and_add(int index, unsigned int hash,87Symbol* name, ClassLoaderData* loader_data,88classloadAction action, Symbol* supername,89Thread* thread);9091void remove_entry(int index, unsigned int hash,92Symbol* name, ClassLoaderData* loader_data);9394// find_and_remove first removes SeenThread for classloadAction95// If all queues are empty and definer is null, remove the PlacheholderEntry completely96void find_and_remove(int index, unsigned int hash,97Symbol* name, ClassLoaderData* loader_data,98classloadAction action, Thread* thread);99100// GC support.101void classes_do(KlassClosure* f);102103// JVMTI support104void entries_do(void f(Symbol*));105106#ifndef PRODUCT107void print();108#endif109void verify();110};111112// SeenThread objects represent list of threads that are113// currently performing a load action on a class.114// For class circularity, set before loading a superclass.115// For bootclasssearchpath, set before calling load_instance_class.116// Defining must be single threaded on a class/classloader basis117// For DEFINE_CLASS, the head of the queue owns the118// define token and the rest of the threads wait to return the119// result the first thread gets.120class SeenThread: public CHeapObj<mtInternal> {121private:122Thread *_thread;123SeenThread* _stnext;124SeenThread* _stprev;125public:126SeenThread(Thread *thread) {127_thread = thread;128_stnext = NULL;129_stprev = NULL;130}131Thread* thread() const { return _thread;}132void set_thread(Thread *thread) { _thread = thread; }133134SeenThread* next() const { return _stnext;}135void set_next(SeenThread *seen) { _stnext = seen; }136void set_prev(SeenThread *seen) { _stprev = seen; }137138#ifndef PRODUCT139void printActionQ() {140SeenThread* seen = this;141while (seen != NULL) {142seen->thread()->print_value();143tty->print(", ");144seen = seen->next();145}146}147#endif // PRODUCT148};149150// Placeholder objects represent classes currently being loaded.151// All threads examining the placeholder table must hold the152// SystemDictionary_lock, so we don't need special precautions153// on store ordering here.154// The system dictionary is the only user of this class.155156class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {157friend class VMStructs;158159160private:161ClassLoaderData* _loader_data; // initiating loader162bool _havesupername; // distinguish between null supername, and unknown163Symbol* _supername;164Thread* _definer; // owner of define token165Klass* _instanceKlass; // InstanceKlass from successful define166SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class167SeenThread* _loadInstanceThreadQ; // loadInstance thread168// can be multiple threads if classloader object lock broken by application169// or if classloader supports parallel classloading170171SeenThread* _defineThreadQ; // queue of Threads trying to define this class172// including _definer173// _definer owns token174// queue waits for and returns results from _definer175176public:177// Simple accessors, used only by SystemDictionary178Symbol* klassname() const { return literal(); }179180ClassLoaderData* loader_data() const { return _loader_data; }181void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; }182183bool havesupername() const { return _havesupername; }184void set_havesupername(bool havesupername) { _havesupername = havesupername; }185186Symbol* supername() const { return _supername; }187void set_supername(Symbol* supername) {188_supername = supername;189if (_supername != NULL) _supername->increment_refcount();190}191192Thread* definer() const {return _definer; }193void set_definer(Thread* definer) { _definer = definer; }194195Klass* instance_klass() const {return _instanceKlass; }196void set_instance_klass(Klass* ik) { _instanceKlass = ik; }197198SeenThread* superThreadQ() const { return _superThreadQ; }199void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }200201SeenThread* loadInstanceThreadQ() const { return _loadInstanceThreadQ; }202void set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }203204SeenThread* defineThreadQ() const { return _defineThreadQ; }205void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }206207PlaceholderEntry* next() const {208return (PlaceholderEntry*)HashtableEntry<Symbol*, mtClass>::next();209}210211PlaceholderEntry** next_addr() {212return (PlaceholderEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();213}214215// Test for equality216// Entries are unique for class/classloader name pair217bool equals(Symbol* class_name, ClassLoaderData* loader) const {218return (klassname() == class_name && loader_data() == loader);219}220221SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {222SeenThread* queuehead = NULL;223switch (action) {224case PlaceholderTable::LOAD_INSTANCE:225queuehead = _loadInstanceThreadQ;226break;227case PlaceholderTable::LOAD_SUPER:228queuehead = _superThreadQ;229break;230case PlaceholderTable::DEFINE_CLASS:231queuehead = _defineThreadQ;232break;233default: Unimplemented();234}235return queuehead;236}237238void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {239switch (action) {240case PlaceholderTable::LOAD_INSTANCE:241_loadInstanceThreadQ = seenthread;242break;243case PlaceholderTable::LOAD_SUPER:244_superThreadQ = seenthread;245break;246case PlaceholderTable::DEFINE_CLASS:247_defineThreadQ = seenthread;248break;249default: Unimplemented();250}251return;252}253254bool super_load_in_progress() {255return (_superThreadQ != NULL);256}257258bool instance_load_in_progress() {259return (_loadInstanceThreadQ != NULL);260}261262bool define_class_in_progress() {263return (_defineThreadQ != NULL);264}265266// Doubly-linked list of Threads per action for class/classloader pair267// Class circularity support: links in thread before loading superclass268// bootstrapsearchpath support: links in a thread before load_instance_class269// definers: use as queue of define requestors, including owner of270// define token. Appends for debugging of requestor order271void add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {272assert_lock_strong(SystemDictionary_lock);273SeenThread* threadEntry = new SeenThread(thread);274SeenThread* seen = actionToQueue(action);275276if (seen == NULL) {277set_threadQ(threadEntry, action);278return;279}280SeenThread* next;281while ((next = seen->next()) != NULL) {282seen = next;283}284seen->set_next(threadEntry);285threadEntry->set_prev(seen);286return;287}288289bool check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {290assert_lock_strong(SystemDictionary_lock);291SeenThread* threadQ = actionToQueue(action);292SeenThread* seen = threadQ;293while (seen) {294if (thread == seen->thread()) {295return true;296}297seen = seen->next();298}299return false;300}301302// returns true if seenthreadQ is now empty303// Note, caller must ensure probe still exists while holding304// SystemDictionary_lock305// ignores if cleanup has already been done306// if found, deletes SeenThread307bool remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {308assert_lock_strong(SystemDictionary_lock);309SeenThread* threadQ = actionToQueue(action);310SeenThread* seen = threadQ;311SeenThread* prev = NULL;312while (seen) {313if (thread == seen->thread()) {314if (prev) {315prev->set_next(seen->next());316} else {317set_threadQ(seen->next(), action);318}319if (seen->next()) {320seen->next()->set_prev(prev);321}322delete seen;323break;324}325prev = seen;326seen = seen->next();327}328return (actionToQueue(action) == NULL);329}330331// GC support332// Applies "f->do_oop" to all root oops in the placeholder table.333void classes_do(KlassClosure* closure);334335// Print method doesn't append a cr336void print() const PRODUCT_RETURN;337void verify() const;338};339340#endif // SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP341342343