1 /*
2 * Copyright (c) 2003, 2025, 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 "oops/symbolHandle.hpp"
29
30 class PlaceholderEntry;
31 class Thread;
32 class ClassLoaderData;
33
34 // Placeholder objects. These represent classes currently
35 // being loaded, as well as arrays of primitives.
36 //
37
38 class PlaceholderTable : public AllStatic {
39 public:
40 // caller to create a placeholder entry must enumerate an action
41 // caller claims ownership of that action
42 // For parallel classloading:
43 // multiple LOAD_INSTANCE threads can proceed in parallel
44 // multiple DETECT_CIRCULARITY threads can proceed in parallel
45 // DETECT_CIRCULARITY needed to check for class circularity
46 // DEFINE_CLASS: ultimately define class must be single threaded
47 // on a class/classloader basis
48 // so the head of that queue owns the token
49 // and the rest of the threads return the result the first thread gets
50 enum classloadAction {
51 LOAD_INSTANCE = 1, // calling load_instance_class
52 DETECT_CIRCULARITY = 2, // loading while detecting class circularity
53 DEFINE_CLASS = 3 // find_or_define class
54 };
55 static void initialize();
56 static PlaceholderEntry* get_entry(Symbol* name, ClassLoaderData* loader_data);
57
58 // find_and_add returns probe pointer - old or new
59 // If no entry exists, add a placeholder entry and push SeenThread for classloadAction
60 // If entry exists, reuse entry and push SeenThread for classloadAction
61 static PlaceholderEntry* find_and_add(Symbol* name, ClassLoaderData* loader_data,
62 classloadAction action, Symbol* supername,
63 JavaThread* thread);
64
65 // find_and_remove first removes SeenThread for classloadAction
66 // If all queues are empty and definer is null, remove the PlacheholderEntry completely
67 static void find_and_remove(Symbol* name, ClassLoaderData* loader_data,
68 classloadAction action, JavaThread* thread);
69
70 static void print_on(outputStream* st);
71 static void print();
72 };
73
74 class SeenThread;
75
76 // Placeholder objects represent classes currently being loaded.
77 // All threads examining the placeholder table must hold the
78 // SystemDictionary_lock, so we don't need special precautions
79 // on store ordering here.
80 // The system dictionary is the only user of this class.
81 class PlaceholderEntry {
82 friend class PlaceholderTable;
83 private:
84 SymbolHandle _next_klass_name; // next step in the recursive process of class loading
85 JavaThread* _definer; // owner of define token
86 InstanceKlass* _instanceKlass; // InstanceKlass from successful define
87 SeenThread* _circularityThreadQ; // doubly-linked queue of Threads loading with circularity detection
88 SeenThread* _loadInstanceThreadQ; // loadInstance thread
89 // This can't be multiple threads since class loading
90 // waits for this token to be removed.
91
92 SeenThread* _defineThreadQ; // queue of Threads trying to define this class
93 // including _definer
94 // _definer owns token
95 // queue waits for and returns results from _definer
96
97 SeenThread* actionToQueue(PlaceholderTable::classloadAction action);
98 void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action);
99 void add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
100 bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
101
102 SeenThread* circularityThreadQ() const { return _circularityThreadQ; }
103 void set_circularityThreadQ(SeenThread* SeenThread) { _circularityThreadQ = SeenThread; }
104
105 SeenThread* loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
106 void set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }
107
108 SeenThread* defineThreadQ() const { return _defineThreadQ; }
109 void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
110 public:
111 PlaceholderEntry() :
112 _definer(nullptr), _instanceKlass(nullptr),
113 _circularityThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }
114
115 Symbol* next_klass_name() const { return _next_klass_name; }
116 void set_next_klass_name(Symbol* next_klass_name);
117
118 JavaThread* definer() const {return _definer; }
119 void set_definer(JavaThread* definer) { _definer = definer; }
120
121 InstanceKlass* instance_klass() const {return _instanceKlass; }
122 void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }
123
124 bool circularity_detection_in_progress() {
125 return (_circularityThreadQ != nullptr);
126 }
127
128 bool instance_load_in_progress() {
129 return (_loadInstanceThreadQ != nullptr);
130 }
131
132 bool define_class_in_progress() {
133 return (_defineThreadQ != nullptr);
134 }
135
136 // Used for ClassCircularityError checking
137 bool check_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
138
139 void print_on(outputStream* st) const;
140 };
141
142 #endif // SHARE_CLASSFILE_PLACEHOLDERS_HPP