placeholders.hpp revision 2062:3582bf76420e
1/*
2 * Copyright (c) 2003, 2010, 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_VM_CLASSFILE_PLACEHOLDERS_HPP
26#define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
27
28#include "runtime/thread.hpp"
29#include "utilities/hashtable.hpp"
30
31class PlaceholderEntry;
32
33// Placeholder objects. These represent classes currently
34// being loaded, as well as arrays of primitives.
35//
36
37class PlaceholderTable : public TwoOopHashtable<Symbol*> {
38  friend class VMStructs;
39
40public:
41  PlaceholderTable(int table_size);
42
43  PlaceholderEntry* new_entry(int hash, Symbol* name, oop loader, bool havesupername, Symbol* supername);
44  void free_entry(PlaceholderEntry* entry);
45
46  PlaceholderEntry* bucket(int i) {
47    return (PlaceholderEntry*)Hashtable<Symbol*>::bucket(i);
48  }
49
50  PlaceholderEntry** bucket_addr(int i) {
51    return (PlaceholderEntry**)Hashtable<Symbol*>::bucket_addr(i);
52  }
53
54  void add_entry(int index, PlaceholderEntry* new_entry) {
55    Hashtable<Symbol*>::add_entry(index, (HashtableEntry<Symbol*>*)new_entry);
56  }
57
58  void add_entry(int index, unsigned int hash, Symbol* name,
59                Handle loader, bool havesupername, Symbol* supername);
60
61  // This returns a Symbol* to match type for SystemDictionary
62  Symbol* find_entry(int index, unsigned int hash,
63                       Symbol* name, Handle loader);
64
65  PlaceholderEntry* get_entry(int index, unsigned int hash,
66                       Symbol* name, Handle loader);
67
68// caller to create a placeholder entry must enumerate an action
69// caller claims ownership of that action
70// For parallel classloading:
71// multiple LOAD_INSTANCE threads can proceed in parallel
72// multiple LOAD_SUPER threads can proceed in parallel
73// LOAD_SUPER needed to check for class circularity
74// DEFINE_CLASS: ultimately define class must be single threaded
75// on a class/classloader basis
76// so the head of that queue owns the token
77// and the rest of the threads return the result the first thread gets
78 enum classloadAction {
79    LOAD_INSTANCE = 1,             // calling load_instance_class
80    LOAD_SUPER = 2,                // loading superclass for this class
81    DEFINE_CLASS = 3               // find_or_define class
82 };
83
84  // find_and_add returns probe pointer - old or new
85  // If no entry exists, add a placeholder entry and push SeenThread
86  // If entry exists, reuse entry and push SeenThread for classloadAction
87  PlaceholderEntry* find_and_add(int index, unsigned int hash,
88                                 Symbol* name, Handle loader,
89                                 classloadAction action, Symbol* supername,
90                                 Thread* thread);
91
92  void remove_entry(int index, unsigned int hash,
93                    Symbol* name, Handle loader);
94
95// Remove placeholder information
96  void find_and_remove(int index, unsigned int hash,
97                       Symbol* name, Handle loader, Thread* thread);
98
99  // GC support.
100  void oops_do(OopClosure* f);
101
102  // JVMTI support
103  void entries_do(void f(Symbol*, oop));
104
105#ifndef PRODUCT
106  void print();
107#endif
108  void verify();
109};
110
111// SeenThread objects represent list of threads that are
112// currently performing a load action on a class.
113// For class circularity, set before loading a superclass.
114// For bootclasssearchpath, set before calling load_instance_class.
115// Defining must be single threaded on a class/classloader basis
116// For DEFINE_CLASS, the head of the queue owns the
117// define token and the rest of the threads wait to return the
118// result the first thread gets.
119class SeenThread: public CHeapObj {
120private:
121   Thread *_thread;
122   SeenThread* _stnext;
123   SeenThread* _stprev;
124public:
125   SeenThread(Thread *thread) {
126       _thread = thread;
127       _stnext = NULL;
128       _stprev = NULL;
129   }
130   Thread* thread()                const { return _thread;}
131   void set_thread(Thread *thread) { _thread = thread; }
132
133   SeenThread* next()              const { return _stnext;}
134   void set_next(SeenThread *seen) { _stnext = seen; }
135   void set_prev(SeenThread *seen) { _stprev = seen; }
136
137#ifndef PRODUCT
138  void printActionQ() {
139    SeenThread* seen = this;
140    while (seen != NULL) {
141      seen->thread()->print_value();
142      tty->print(", ");
143      seen = seen->next();
144    }
145  }
146#endif // PRODUCT
147};
148
149// Placeholder objects represent classes currently being loaded.
150// All threads examining the placeholder table must hold the
151// SystemDictionary_lock, so we don't need special precautions
152// on store ordering here.
153// The system dictionary is the only user of this class.
154
155class PlaceholderEntry : public HashtableEntry<Symbol*> {
156  friend class VMStructs;
157
158
159 private:
160  oop               _loader;        // initiating loader
161  bool              _havesupername; // distinguish between null supername, and unknown
162  Symbol*           _supername;
163  Thread*           _definer;       // owner of define token
164  klassOop          _instanceKlass; // instanceKlass from successful define
165  SeenThread*       _superThreadQ;  // doubly-linked queue of Threads loading a superclass for this class
166  SeenThread*       _loadInstanceThreadQ;  // loadInstance thread
167                                    // can be multiple threads if classloader object lock broken by application
168                                    // or if classloader supports parallel classloading
169
170  SeenThread*       _defineThreadQ; // queue of Threads trying to define this class
171                                    // including _definer
172                                    // _definer owns token
173                                    // queue waits for and returns results from _definer
174
175 public:
176  // Simple accessors, used only by SystemDictionary
177  Symbol*            klassname()           const { return literal(); }
178
179  oop                loader()              const { return _loader; }
180  void               set_loader(oop loader) { _loader = loader; }
181  oop*               loader_addr()         { return &_loader; }
182
183  bool               havesupername()       const { return _havesupername; }
184  void               set_havesupername(bool havesupername) { _havesupername = havesupername; }
185
186  Symbol*            supername()           const { return _supername; }
187  void               set_supername(Symbol* supername) {
188    _supername = supername;
189    if (_supername != NULL) _supername->increment_refcount();
190  }
191
192  Thread*            definer()             const {return _definer; }
193  void               set_definer(Thread* definer) { _definer = definer; }
194
195  klassOop           instanceKlass()     const {return _instanceKlass; }
196  void               set_instanceKlass(klassOop instanceKlass) { _instanceKlass = instanceKlass; }
197  klassOop*          instanceKlass_addr()   { return &_instanceKlass; }
198
199  SeenThread*        superThreadQ()        const { return _superThreadQ; }
200  void               set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
201
202  SeenThread*        loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
203  void               set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }
204
205  SeenThread*        defineThreadQ()        const { return _defineThreadQ; }
206  void               set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
207
208  PlaceholderEntry* next() const {
209    return (PlaceholderEntry*)HashtableEntry<Symbol*>::next();
210  }
211
212  PlaceholderEntry** next_addr() {
213    return (PlaceholderEntry**)HashtableEntry<Symbol*>::next_addr();
214  }
215
216  // Test for equality
217  // Entries are unique for class/classloader name pair
218  bool equals(Symbol* class_name, oop class_loader) const {
219    return (klassname() == class_name && loader() == class_loader);
220  }
221
222  SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {
223    SeenThread* queuehead;
224    switch (action) {
225      case PlaceholderTable::LOAD_INSTANCE:
226         queuehead = _loadInstanceThreadQ;
227         break;
228      case PlaceholderTable::LOAD_SUPER:
229         queuehead = _superThreadQ;
230         break;
231      case PlaceholderTable::DEFINE_CLASS:
232         queuehead = _defineThreadQ;
233         break;
234      default: Unimplemented();
235    }
236    return queuehead;
237  }
238
239  void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
240    switch (action) {
241      case PlaceholderTable::LOAD_INSTANCE:
242         _loadInstanceThreadQ = seenthread;
243         break;
244      case PlaceholderTable::LOAD_SUPER:
245         _superThreadQ = seenthread;
246         break;
247      case PlaceholderTable::DEFINE_CLASS:
248         _defineThreadQ = seenthread;
249         break;
250      default: Unimplemented();
251    }
252    return;
253  }
254
255  bool super_load_in_progress() {
256     return (_superThreadQ != NULL);
257  }
258
259  bool instance_load_in_progress() {
260    return (_loadInstanceThreadQ != NULL);
261  }
262
263  bool define_class_in_progress() {
264    return (_defineThreadQ != NULL);
265  }
266
267// Doubly-linked list of Threads per action for class/classloader pair
268// Class circularity support: links in thread before loading superclass
269// bootstrapsearchpath support: links in a thread before load_instance_class
270// definers: use as queue of define requestors, including owner of
271// define token. Appends for debugging of requestor order
272  void add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
273    assert_lock_strong(SystemDictionary_lock);
274    SeenThread* threadEntry = new SeenThread(thread);
275    SeenThread* seen = actionToQueue(action);
276
277    if (seen == NULL) {
278      set_threadQ(threadEntry, action);
279      return;
280    }
281    SeenThread* next;
282    while ((next = seen->next()) != NULL) {
283      seen = next;
284    }
285    seen->set_next(threadEntry);
286    threadEntry->set_prev(seen);
287    return;
288  }
289
290  bool check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
291    assert_lock_strong(SystemDictionary_lock);
292    SeenThread* threadQ = actionToQueue(action);
293    SeenThread* seen = threadQ;
294    while (seen) {
295      if (thread == seen->thread()) {
296        return true;
297      }
298      seen = seen->next();
299    }
300    return false;
301  }
302
303  // returns true if seenthreadQ is now empty
304  // Note, caller must ensure probe still exists while holding
305  // SystemDictionary_lock
306  // ignores if cleanup has already been done
307  // if found, deletes SeenThread
308  bool remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
309    assert_lock_strong(SystemDictionary_lock);
310    SeenThread* threadQ = actionToQueue(action);
311    SeenThread* seen = threadQ;
312    SeenThread* prev = NULL;
313    while (seen) {
314      if (thread == seen->thread()) {
315        if (prev) {
316          prev->set_next(seen->next());
317        } else {
318          set_threadQ(seen->next(), action);
319        }
320        if (seen->next()) {
321          seen->next()->set_prev(prev);
322        }
323        delete seen;
324        break;
325      }
326      prev = seen;
327      seen = seen->next();
328    }
329    return (actionToQueue(action) == NULL);
330  }
331
332  // GC support
333  // Applies "f->do_oop" to all root oops in the placeholder table.
334  void oops_do(OopClosure* blk);
335
336  // Print method doesn't append a cr
337  void print() const  PRODUCT_RETURN;
338  void verify() const;
339};
340
341#endif // SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
342