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