45 }
46 static unsigned hash(PlaceholderKey const& k) {
47 return (unsigned) k._name->identity_hash() ^ (int)((intptr_t)k._loader_data >> 3);
48 }
49 void print_on(outputStream* st) const;
50 };
51
52 const int _placeholder_table_size = 503; // Does this really have to be prime?
53 using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
54 PlaceholderKey::hash, PlaceholderKey::equals>;
55 static InternalPlaceholderTable* _placeholders;
56
57 // SeenThread objects represent list of threads that are
58 // currently performing a load action on a class.
59 // For class circularity, set before loading a superclass.
60 // For bootclasssearchpath, set before calling load_instance_class.
61 // Defining must be single threaded on a class/classloader basis
62 // For DEFINE_CLASS, the head of the queue owns the
63 // define token and the rest of the threads wait to return the
64 // result the first thread gets.
65 class SeenThread: public CHeapObj<mtInternal> {
66 private:
67 JavaThread* _thread;
68 SeenThread* _stnext;
69 SeenThread* _stprev;
70 public:
71 SeenThread(JavaThread* thread) {
72 _thread = thread;
73 _stnext = nullptr;
74 _stprev = nullptr;
75 }
76 JavaThread* thread() const { return _thread;}
77 void set_thread(JavaThread* thread) { _thread = thread; }
78
79 SeenThread* next() const { return _stnext;}
80 void set_next(SeenThread* seen) { _stnext = seen; }
81 void set_prev(SeenThread* seen) { _stprev = seen; }
82
83 void print_action_queue(outputStream* st) {
84 SeenThread* seen = this;
85 while (seen != nullptr) {
86 seen->thread()->print_value_on(st);
87 st->print(", ");
88 seen = seen->next();
89 }
90 }
91 };
92
93 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
94 SeenThread* queuehead = nullptr;
95 switch (action) {
96 case PlaceholderTable::LOAD_INSTANCE:
97 queuehead = _loadInstanceThreadQ;
98 break;
99 case PlaceholderTable::LOAD_SUPER:
100 queuehead = _superThreadQ;
101 break;
102 case PlaceholderTable::DEFINE_CLASS:
103 queuehead = _defineThreadQ;
104 break;
105 default: Unimplemented();
106 }
107 return queuehead;
108 }
109
110 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
111 switch (action) {
112 case PlaceholderTable::LOAD_INSTANCE:
113 _loadInstanceThreadQ = seenthread;
114 break;
115 case PlaceholderTable::LOAD_SUPER:
116 _superThreadQ = seenthread;
117 break;
118 case PlaceholderTable::DEFINE_CLASS:
119 _defineThreadQ = seenthread;
120 break;
121 default: Unimplemented();
122 }
123 return;
124 }
125
126 // Doubly-linked list of Threads per action for class/classloader pair
127 // Class circularity support: links in thread before loading superclass
128 // bootstrap loader support: links in a thread before load_instance_class
129 // definers: use as queue of define requestors, including owner of
130 // define token. Appends for debugging of requestor order
131 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
132 assert_lock_strong(SystemDictionary_lock);
133 SeenThread* threadEntry = new SeenThread(thread);
134 SeenThread* seen = actionToQueue(action);
135
136 if (seen == nullptr) {
137 set_threadQ(threadEntry, action);
138 return;
139 }
140 SeenThread* next;
216 // Remove a placeholder object.
217 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
218 assert_locked_or_safepoint(SystemDictionary_lock);
219
220 PlaceholderKey key(class_name, loader_data);
221 _placeholders->remove(key);
222 }
223
224
225 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
226 assert_locked_or_safepoint(SystemDictionary_lock);
227 PlaceholderKey key(class_name, loader_data);
228 return _placeholders->get(key);
229 }
230
231 static const char* action_to_string(PlaceholderTable::classloadAction action) {
232 switch (action) {
233 case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
234 case PlaceholderTable::LOAD_SUPER: return "LOAD_SUPER";
235 case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
236 }
237 return "";
238 }
239
240 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
241 if (log_is_enabled(Debug, class, load, placeholders)) {
242 LogTarget(Debug, class, load, placeholders) lt;
243 ResourceMark rm;
244 LogStream ls(lt);
245 ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
246 entry->print_on(&ls);
247 }
248 }
249
250 // find_and_add returns probe pointer - old or new
251 // If no entry exists, add a placeholder entry
252 // If entry exists, reuse entry
253 // For both, push SeenThread for classloadAction
254 // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
255 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
284 // defineThreadQ tracks waiters on defining thread's results
285 // 1st claimant creates placeholder
286 // find_and_add adds SeenThread entry for appropriate queue
287 // All claimants remove SeenThread after completing action
288 // On removal: if definer and all queues empty, remove entry
289 // Note: you can be in both placeholders and systemDictionary
290 // Therefore - must always check SD first
291 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
292 classloadAction action,
293 JavaThread* thread) {
294 assert_locked_or_safepoint(SystemDictionary_lock);
295 PlaceholderEntry* probe = get_entry(name, loader_data);
296 assert(probe != nullptr, "must find an entry");
297 log(name, probe, "find_and_remove", action);
298 probe->remove_seen_thread(thread, action);
299 if (probe->superThreadQ() == nullptr) {
300 probe->set_supername(nullptr);
301 }
302 // If no other threads using this entry, and this thread is not using this entry for other states
303 if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
304 && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
305 remove_entry(name, loader_data);
306 }
307 }
308
309 void PlaceholderKey::print_on(outputStream* st) const {
310 _name->print_value_on(st);
311 st->print(", loader ");
312 _loader_data->print_value_on(st);
313 }
314
315 void PlaceholderEntry::print_on(outputStream* st) const {
316 if (supername() != nullptr) {
317 st->print(", supername ");
318 supername()->print_value_on(st);
319 }
320 if (definer() != nullptr) {
321 st->print(", definer ");
322 definer()->print_value_on(st);
323 }
324 if (instance_klass() != nullptr) {
325 st->print(", InstanceKlass ");
326 instance_klass()->print_value_on(st);
327 }
328 st->cr();
329 st->print("loadInstanceThreadQ threads:");
330 loadInstanceThreadQ()->print_action_queue(st);
331 st->cr();
332 st->print("superThreadQ threads:");
333 superThreadQ()->print_action_queue(st);
334 st->cr();
335 st->print("defineThreadQ threads:");
336 defineThreadQ()->print_action_queue(st);
337 st->cr();
338 }
339
340 void PlaceholderTable::print_on(outputStream* st) {
341 auto printer = [&] (PlaceholderKey& key, PlaceholderEntry& entry) {
342 st->print("placeholder ");
343 key.print_on(st);
344 entry.print_on(st);
345 return true;
346 };
347 st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
348 _placeholders->table_size(), _placeholders->number_of_entries());
349 _placeholders->iterate(printer);
350 }
351
352 void PlaceholderTable::print() { return print_on(tty); }
|
45 }
46 static unsigned hash(PlaceholderKey const& k) {
47 return (unsigned) k._name->identity_hash() ^ (int)((intptr_t)k._loader_data >> 3);
48 }
49 void print_on(outputStream* st) const;
50 };
51
52 const int _placeholder_table_size = 503; // Does this really have to be prime?
53 using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
54 PlaceholderKey::hash, PlaceholderKey::equals>;
55 static InternalPlaceholderTable* _placeholders;
56
57 // SeenThread objects represent list of threads that are
58 // currently performing a load action on a class.
59 // For class circularity, set before loading a superclass.
60 // For bootclasssearchpath, set before calling load_instance_class.
61 // Defining must be single threaded on a class/classloader basis
62 // For DEFINE_CLASS, the head of the queue owns the
63 // define token and the rest of the threads wait to return the
64 // result the first thread gets.
65 // For INLINE_FIELD, set when loading inline type fields for
66 // class circularity checking.
67 class SeenThread: public CHeapObj<mtInternal> {
68 private:
69 JavaThread* _thread;
70 SeenThread* _stnext;
71 SeenThread* _stprev;
72 public:
73 SeenThread(JavaThread* thread) {
74 _thread = thread;
75 _stnext = nullptr;
76 _stprev = nullptr;
77 }
78 JavaThread* thread() const { return _thread;}
79 void set_thread(JavaThread* thread) { _thread = thread; }
80
81 SeenThread* next() const { return _stnext;}
82 void set_next(SeenThread* seen) { _stnext = seen; }
83 void set_prev(SeenThread* seen) { _stprev = seen; }
84
85 void print_action_queue(outputStream* st) {
86 SeenThread* seen = this;
87 while (seen != nullptr) {
88 seen->thread()->print_value_on(st);
89 st->print(", ");
90 seen = seen->next();
91 }
92 }
93 };
94
95 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
96 SeenThread* queuehead = nullptr;
97 switch (action) {
98 case PlaceholderTable::LOAD_INSTANCE:
99 queuehead = _loadInstanceThreadQ;
100 break;
101 case PlaceholderTable::LOAD_SUPER:
102 queuehead = _superThreadQ;
103 break;
104 case PlaceholderTable::DEFINE_CLASS:
105 queuehead = _defineThreadQ;
106 break;
107 case PlaceholderTable::PRIMITIVE_OBJECT_FIELD:
108 queuehead = _inlineTypeFieldQ;
109 break;
110 default: Unimplemented();
111 }
112 return queuehead;
113 }
114
115 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
116 switch (action) {
117 case PlaceholderTable::LOAD_INSTANCE:
118 _loadInstanceThreadQ = seenthread;
119 break;
120 case PlaceholderTable::LOAD_SUPER:
121 _superThreadQ = seenthread;
122 break;
123 case PlaceholderTable::DEFINE_CLASS:
124 _defineThreadQ = seenthread;
125 break;
126 case PlaceholderTable::PRIMITIVE_OBJECT_FIELD:
127 _inlineTypeFieldQ = seenthread;
128 break;
129 default: Unimplemented();
130 }
131 return;
132 }
133
134 // Doubly-linked list of Threads per action for class/classloader pair
135 // Class circularity support: links in thread before loading superclass
136 // bootstrap loader support: links in a thread before load_instance_class
137 // definers: use as queue of define requestors, including owner of
138 // define token. Appends for debugging of requestor order
139 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
140 assert_lock_strong(SystemDictionary_lock);
141 SeenThread* threadEntry = new SeenThread(thread);
142 SeenThread* seen = actionToQueue(action);
143
144 if (seen == nullptr) {
145 set_threadQ(threadEntry, action);
146 return;
147 }
148 SeenThread* next;
224 // Remove a placeholder object.
225 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
226 assert_locked_or_safepoint(SystemDictionary_lock);
227
228 PlaceholderKey key(class_name, loader_data);
229 _placeholders->remove(key);
230 }
231
232
233 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
234 assert_locked_or_safepoint(SystemDictionary_lock);
235 PlaceholderKey key(class_name, loader_data);
236 return _placeholders->get(key);
237 }
238
239 static const char* action_to_string(PlaceholderTable::classloadAction action) {
240 switch (action) {
241 case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
242 case PlaceholderTable::LOAD_SUPER: return "LOAD_SUPER";
243 case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
244 case PlaceholderTable::PRIMITIVE_OBJECT_FIELD: return "PRIMITIVE_OBJECT_FIELD";
245 }
246 return "";
247 }
248
249 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
250 if (log_is_enabled(Debug, class, load, placeholders)) {
251 LogTarget(Debug, class, load, placeholders) lt;
252 ResourceMark rm;
253 LogStream ls(lt);
254 ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
255 entry->print_on(&ls);
256 }
257 }
258
259 // find_and_add returns probe pointer - old or new
260 // If no entry exists, add a placeholder entry
261 // If entry exists, reuse entry
262 // For both, push SeenThread for classloadAction
263 // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
264 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
293 // defineThreadQ tracks waiters on defining thread's results
294 // 1st claimant creates placeholder
295 // find_and_add adds SeenThread entry for appropriate queue
296 // All claimants remove SeenThread after completing action
297 // On removal: if definer and all queues empty, remove entry
298 // Note: you can be in both placeholders and systemDictionary
299 // Therefore - must always check SD first
300 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
301 classloadAction action,
302 JavaThread* thread) {
303 assert_locked_or_safepoint(SystemDictionary_lock);
304 PlaceholderEntry* probe = get_entry(name, loader_data);
305 assert(probe != nullptr, "must find an entry");
306 log(name, probe, "find_and_remove", action);
307 probe->remove_seen_thread(thread, action);
308 if (probe->superThreadQ() == nullptr) {
309 probe->set_supername(nullptr);
310 }
311 // If no other threads using this entry, and this thread is not using this entry for other states
312 if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
313 && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)
314 && (probe->inlineTypeFieldQ() == nullptr)) {
315 remove_entry(name, loader_data);
316 }
317 }
318
319 void PlaceholderKey::print_on(outputStream* st) const {
320 _name->print_value_on(st);
321 st->print(", loader ");
322 _loader_data->print_value_on(st);
323 }
324
325 void PlaceholderEntry::print_on(outputStream* st) const {
326 if (supername() != nullptr) {
327 st->print(", supername ");
328 supername()->print_value_on(st);
329 }
330 if (definer() != nullptr) {
331 st->print(", definer ");
332 definer()->print_value_on(st);
333 }
334 if (instance_klass() != nullptr) {
335 st->print(", InstanceKlass ");
336 instance_klass()->print_value_on(st);
337 }
338 st->cr();
339 st->print("loadInstanceThreadQ threads:");
340 loadInstanceThreadQ()->print_action_queue(st);
341 st->cr();
342 st->print("superThreadQ threads:");
343 superThreadQ()->print_action_queue(st);
344 st->cr();
345 st->print("defineThreadQ threads:");
346 defineThreadQ()->print_action_queue(st);
347 st->cr();
348 st->print("inlineTypeFieldQ threads:");
349 inlineTypeFieldQ()->print_action_queue(st);
350 st->cr();
351 }
352
353 void PlaceholderTable::print_on(outputStream* st) {
354 auto printer = [&] (PlaceholderKey& key, PlaceholderEntry& entry) {
355 st->print("placeholder ");
356 key.print_on(st);
357 entry.print_on(st);
358 return true;
359 };
360 st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
361 _placeholders->table_size(), _placeholders->number_of_entries());
362 _placeholders->iterate(printer);
363 }
364
365 void PlaceholderTable::print() { return print_on(tty); }
|