1 /*
  2  * Copyright (c) 2003, 2021, 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 "utilities/hashtable.hpp"
 29 
 30 class PlaceholderEntry;
 31 class Thread;
 32 class ClassLoaderData;
 33 class Symbol;
 34 
 35 // Placeholder objects. These represent classes currently
 36 // being loaded, as well as arrays of primitives.
 37 //
 38 
 39 class PlaceholderTable : public Hashtable<Symbol*, mtClass> {
 40 
 41 public:
 42   PlaceholderTable(int table_size);
 43 
 44   PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, Symbol* supername);
 45   void free_entry(PlaceholderEntry* entry);
 46 
 47   PlaceholderEntry* bucket(int i) const {
 48     return (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
 49   }
 50 
 51   PlaceholderEntry** bucket_addr(int i) {
 52     return (PlaceholderEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
 53   }
 54 
 55   PlaceholderEntry* add_entry(unsigned int hash, Symbol* name,
 56                               ClassLoaderData* loader_data,
 57                               Symbol* supername);
 58 
 59   // This returns a Symbol* to match type for SystemDictionary
 60   Symbol* find_entry(unsigned int hash,
 61                      Symbol* name, ClassLoaderData* loader_data);
 62 
 63   PlaceholderEntry* get_entry(unsigned int hash,
 64                               Symbol* name, ClassLoaderData* loader_data);
 65 
 66 // caller to create a placeholder entry must enumerate an action
 67 // caller claims ownership of that action
 68 // For parallel classloading:
 69 // multiple LOAD_INSTANCE threads can proceed in parallel
 70 // multiple LOAD_SUPER threads can proceed in parallel
 71 // LOAD_SUPER needed to check for class circularity
 72 // DEFINE_CLASS: ultimately define class must be single threaded
 73 // on a class/classloader basis
 74 // so the head of that queue owns the token
 75 // and the rest of the threads return the result the first thread gets
 76 // INLINE_TYPE_FIELD: needed to check for inline type fields circularity
 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     INLINE_TYPE_FIELD = 4          // inline type fields
 82  };
 83 
 84   // find_and_add returns probe pointer - old or new
 85   // If no entry exists, add a placeholder entry and push SeenThread for classloadAction
 86   // If entry exists, reuse entry and push SeenThread for classloadAction
 87   PlaceholderEntry* find_and_add(unsigned int hash,
 88                                  Symbol* name, ClassLoaderData* loader_data,
 89                                  classloadAction action, Symbol* supername,
 90                                  JavaThread* thread);
 91 
 92   void remove_entry(unsigned int hash,
 93                     Symbol* name, ClassLoaderData* loader_data);
 94 
 95   // find_and_remove first removes SeenThread for classloadAction
 96   // If all queues are empty and definer is null, remove the PlacheholderEntry completely
 97   void find_and_remove(unsigned int hash,
 98                        Symbol* name, ClassLoaderData* loader_data,
 99                        classloadAction action, JavaThread* thread);
100 
101   void print_on(outputStream* st) const;
102   void print() const;
103   void verify();
104 };
105 
106 class SeenThread;
107 
108 // Placeholder objects represent classes currently being loaded.
109 // All threads examining the placeholder table must hold the
110 // SystemDictionary_lock, so we don't need special precautions
111 // on store ordering here.
112 // The system dictionary is the only user of this class.
113 
114 class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {
115 
116   friend class PlaceholderTable;
117 
118  private:
119   ClassLoaderData*  _loader_data;   // initiating loader
120   Symbol*           _supername;
121   JavaThread*       _definer;       // owner of define token
122   InstanceKlass*    _instanceKlass; // InstanceKlass from successful define
123   SeenThread*       _superThreadQ;  // doubly-linked queue of Threads loading a superclass for this class
124   SeenThread*       _loadInstanceThreadQ;  // loadInstance thread
125                                     // This can't be multiple threads since class loading waits for
126                                     // this token to be removed.
127 
128   SeenThread*       _defineThreadQ; // queue of Threads trying to define this class
129                                     // including _definer
130                                     // _definer owns token
131                                     // queue waits for and returns results from _definer
132   SeenThread*       _inlineTypeFieldQ;  // queue of inline types for circularity checking
133 
134   SeenThread* actionToQueue(PlaceholderTable::classloadAction action);
135   void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action);
136   void add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
137   bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
138 
139  public:
140   // Simple accessors, used only by SystemDictionary
141   Symbol*            klassname()           const { return literal(); }
142 
143   ClassLoaderData*   loader_data()         const { return _loader_data; }
144   void               set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; }
145 
146   Symbol*            supername()           const { return _supername; }
147   void               set_supername(Symbol* supername) {
148     _supername = supername;
149     if (_supername != NULL) _supername->increment_refcount();
150   }
151 
152   JavaThread*        definer()             const {return _definer; }
153   void               set_definer(JavaThread* definer) { _definer = definer; }
154 
155   InstanceKlass*     instance_klass()      const {return _instanceKlass; }
156   void               set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }
157 
158   SeenThread*        superThreadQ()        const { return _superThreadQ; }
159   void               set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
160 
161   SeenThread*        loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
162   void               set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }
163 
164   SeenThread*        defineThreadQ()       const { return _defineThreadQ; }
165   void               set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
166 
167   SeenThread*        inlineTypeFieldQ()    const { return _inlineTypeFieldQ; }
168   void               set_inlineTypeFieldQ(SeenThread* SeenThread) { _inlineTypeFieldQ = SeenThread; }
169 
170   PlaceholderEntry* next() const {
171     return (PlaceholderEntry*)HashtableEntry<Symbol*, mtClass>::next();
172   }
173 
174   PlaceholderEntry** next_addr() {
175     return (PlaceholderEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
176   }
177 
178   // Test for equality
179   // Entries are unique for class/classloader name pair
180   bool equals(Symbol* class_name, ClassLoaderData* loader) const {
181     return (klassname() == class_name && loader_data() == loader);
182   }
183 
184   bool super_load_in_progress() {
185      return (_superThreadQ != NULL);
186   }
187 
188   bool instance_load_in_progress() {
189     return (_loadInstanceThreadQ != NULL);
190   }
191 
192   bool define_class_in_progress() {
193     return (_defineThreadQ != NULL);
194   }
195 
196   bool inline_type_field_in_progress() {
197     return (_inlineTypeFieldQ != NULL);
198   }
199 
200   // Used for ClassCircularityError checking
201   bool check_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
202 
203   // Print method doesn't append a cr
204   void print_entry(outputStream* st) const;
205   void verify() const;
206 };
207 
208 #endif // SHARE_CLASSFILE_PLACEHOLDERS_HPP