< prev index next >

src/hotspot/share/classfile/placeholders.cpp

Print this page

 44     return (k1._name == k2._name && k1._loader_data == k2._loader_data);
 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 ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
 54                   PlaceholderKey::hash, PlaceholderKey::equals> _placeholders;
 55 
 56 // SeenThread objects represent list of threads that are
 57 // currently performing a load action on a class.
 58 // For class circularity, set before loading a superclass.
 59 // For bootclasssearchpath, set before calling load_instance_class.
 60 // Defining must be single threaded on a class/classloader basis
 61 // For DEFINE_CLASS, the head of the queue owns the
 62 // define token and the rest of the threads wait to return the
 63 // result the first thread gets.


 64 class SeenThread: public CHeapObj<mtInternal> {
 65 private:
 66    JavaThread* _thread;
 67    SeenThread* _stnext;
 68    SeenThread* _stprev;
 69 public:
 70    SeenThread(JavaThread* thread) {
 71        _thread = thread;
 72        _stnext = NULL;
 73        _stprev = NULL;
 74    }
 75    JavaThread* thread()          const { return _thread;}
 76    void set_thread(JavaThread* thread) { _thread = thread; }
 77 
 78    SeenThread* next()        const { return _stnext;}
 79    void set_next(SeenThread* seen) { _stnext = seen; }
 80    void set_prev(SeenThread* seen) { _stprev = seen; }
 81 
 82   void print_action_queue(outputStream* st) {
 83     SeenThread* seen = this;
 84     while (seen != NULL) {
 85       seen->thread()->print_value_on(st);
 86       st->print(", ");
 87       seen = seen->next();
 88     }
 89   }
 90 };
 91 
 92 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
 93   SeenThread* queuehead = NULL;
 94   switch (action) {
 95     case PlaceholderTable::LOAD_INSTANCE:
 96        queuehead = _loadInstanceThreadQ;
 97        break;
 98     case PlaceholderTable::LOAD_SUPER:
 99        queuehead = _superThreadQ;
100        break;
101     case PlaceholderTable::DEFINE_CLASS:
102        queuehead = _defineThreadQ;
103        break;



104     default: Unimplemented();
105   }
106   return queuehead;
107 }
108 
109 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
110   switch (action) {
111     case PlaceholderTable::LOAD_INSTANCE:
112        _loadInstanceThreadQ = seenthread;
113        break;
114     case PlaceholderTable::LOAD_SUPER:
115        _superThreadQ = seenthread;
116        break;
117     case PlaceholderTable::DEFINE_CLASS:
118        _defineThreadQ = seenthread;
119        break;



120     default: Unimplemented();
121   }
122   return;
123 }
124 
125 // Doubly-linked list of Threads per action for class/classloader pair
126 // Class circularity support: links in thread before loading superclass
127 // bootstrap loader support:  links in a thread before load_instance_class
128 // definers: use as queue of define requestors, including owner of
129 // define token. Appends for debugging of requestor order
130 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
131   assert_lock_strong(SystemDictionary_lock);
132   SeenThread* threadEntry = new SeenThread(thread);
133   SeenThread* seen = actionToQueue(action);
134 
135   assert(action != PlaceholderTable::LOAD_INSTANCE || !EnableWaitForParallelLoad || seen == NULL,
136          "Only one LOAD_INSTANCE allowed at a time");
137 
138   if (seen == NULL) {
139     set_threadQ(threadEntry, action);

214 // Remove a placeholder object.
215 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
216   assert_locked_or_safepoint(SystemDictionary_lock);
217 
218   PlaceholderKey key(class_name, loader_data);
219   _placeholders.remove(key);
220 }
221 
222 
223 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
224   assert_locked_or_safepoint(SystemDictionary_lock);
225   PlaceholderKey key(class_name, loader_data);
226   return _placeholders.get(key);
227 }
228 
229 static const char* action_to_string(PlaceholderTable::classloadAction action) {
230   switch (action) {
231   case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
232   case PlaceholderTable::LOAD_SUPER:    return "LOAD_SUPER";
233   case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";

234  }
235  return "";
236 }
237 
238 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
239   if (log_is_enabled(Debug, class, load, placeholders)) {
240     LogTarget(Debug, class, load, placeholders) lt;
241     ResourceMark rm;
242     LogStream ls(lt);
243     ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
244     entry->print_on(&ls);
245   }
246 }
247 
248 // find_and_add returns probe pointer - old or new
249 // If no entry exists, add a placeholder entry
250 // If entry exists, reuse entry
251 // For both, push SeenThread for classloadAction
252 // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
253 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,

277 // loadInstanceThreadQ tracks load_instance_class calls
278 // definer() tracks the single thread that owns define token
279 // defineThreadQ tracks waiters on defining thread's results
280 // 1st claimant creates placeholder
281 // find_and_add adds SeenThread entry for appropriate queue
282 // All claimants remove SeenThread after completing action
283 // On removal: if definer and all queues empty, remove entry
284 // Note: you can be in both placeholders and systemDictionary
285 // Therefore - must always check SD first
286 // Ignores the case where entry is not found
287 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
288                                        classloadAction action,
289                                        JavaThread* thread) {
290   assert_locked_or_safepoint(SystemDictionary_lock);
291   PlaceholderEntry* probe = get_entry(name, loader_data);
292   if (probe != NULL) {
293     log(name, probe, "find_and_remove", action);
294     probe->remove_seen_thread(thread, action);
295     // If no other threads using this entry, and this thread is not using this entry for other states
296     if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL)
297         && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) {

298       probe->clear_supername();
299       remove_entry(name, loader_data);
300     }
301   }
302 }
303 
304 void PlaceholderKey::print_on(outputStream* st) const {
305   _name->print_value_on(st);
306   st->print(", loader ");
307   _loader_data->print_value_on(st);
308 }
309 
310 void PlaceholderEntry::print_on(outputStream* st) const {
311   if (supername() != NULL) {
312     st->print(", supername ");
313     supername()->print_value_on(st);
314   }
315   if (definer() != NULL) {
316     st->print(", definer ");
317     definer()->print_value_on(st);
318   }
319   if (instance_klass() != NULL) {
320     st->print(", InstanceKlass ");
321     instance_klass()->print_value_on(st);
322   }
323   st->cr();
324   st->print("loadInstanceThreadQ threads:");
325   loadInstanceThreadQ()->print_action_queue(st);
326   st->cr();
327   st->print("superThreadQ threads:");
328   superThreadQ()->print_action_queue(st);
329   st->cr();
330   st->print("defineThreadQ threads:");
331   defineThreadQ()->print_action_queue(st);
332   st->cr();



333 }
334 
335 void PlaceholderTable::print_on(outputStream* st) {
336   auto printer = [&] (PlaceholderKey& key, PlaceholderEntry& entry) {
337       st->print("placeholder ");
338       key.print_on(st);
339       entry.print_on(st);
340       return true;
341   };
342   st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
343                 _placeholders.table_size(), _placeholders.number_of_entries());
344   _placeholders.iterate(printer);
345 }
346 
347 void PlaceholderTable::print() { return print_on(tty); }

 44     return (k1._name == k2._name && k1._loader_data == k2._loader_data);
 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 ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
 54                   PlaceholderKey::hash, PlaceholderKey::equals> _placeholders;
 55 
 56 // SeenThread objects represent list of threads that are
 57 // currently performing a load action on a class.
 58 // For class circularity, set before loading a superclass.
 59 // For bootclasssearchpath, set before calling load_instance_class.
 60 // Defining must be single threaded on a class/classloader basis
 61 // For DEFINE_CLASS, the head of the queue owns the
 62 // define token and the rest of the threads wait to return the
 63 // result the first thread gets.
 64 // For INLINE_FIELD, set when loading inline type fields for
 65 // class circularity checking.
 66 class SeenThread: public CHeapObj<mtInternal> {
 67 private:
 68    JavaThread* _thread;
 69    SeenThread* _stnext;
 70    SeenThread* _stprev;
 71 public:
 72    SeenThread(JavaThread* thread) {
 73        _thread = thread;
 74        _stnext = NULL;
 75        _stprev = NULL;
 76    }
 77    JavaThread* thread()          const { return _thread;}
 78    void set_thread(JavaThread* thread) { _thread = thread; }
 79 
 80    SeenThread* next()        const { return _stnext;}
 81    void set_next(SeenThread* seen) { _stnext = seen; }
 82    void set_prev(SeenThread* seen) { _stprev = seen; }
 83 
 84   void print_action_queue(outputStream* st) {
 85     SeenThread* seen = this;
 86     while (seen != NULL) {
 87       seen->thread()->print_value_on(st);
 88       st->print(", ");
 89       seen = seen->next();
 90     }
 91   }
 92 };
 93 
 94 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
 95   SeenThread* queuehead = NULL;
 96   switch (action) {
 97     case PlaceholderTable::LOAD_INSTANCE:
 98        queuehead = _loadInstanceThreadQ;
 99        break;
100     case PlaceholderTable::LOAD_SUPER:
101        queuehead = _superThreadQ;
102        break;
103     case PlaceholderTable::DEFINE_CLASS:
104        queuehead = _defineThreadQ;
105        break;
106     case PlaceholderTable::PRIMITIVE_OBJECT_FIELD:
107        queuehead = _inlineTypeFieldQ;
108        break;
109     default: Unimplemented();
110   }
111   return queuehead;
112 }
113 
114 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
115   switch (action) {
116     case PlaceholderTable::LOAD_INSTANCE:
117        _loadInstanceThreadQ = seenthread;
118        break;
119     case PlaceholderTable::LOAD_SUPER:
120        _superThreadQ = seenthread;
121        break;
122     case PlaceholderTable::DEFINE_CLASS:
123        _defineThreadQ = seenthread;
124        break;
125     case PlaceholderTable::PRIMITIVE_OBJECT_FIELD:
126        _inlineTypeFieldQ = seenthread;
127        break;
128     default: Unimplemented();
129   }
130   return;
131 }
132 
133 // Doubly-linked list of Threads per action for class/classloader pair
134 // Class circularity support: links in thread before loading superclass
135 // bootstrap loader support:  links in a thread before load_instance_class
136 // definers: use as queue of define requestors, including owner of
137 // define token. Appends for debugging of requestor order
138 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
139   assert_lock_strong(SystemDictionary_lock);
140   SeenThread* threadEntry = new SeenThread(thread);
141   SeenThread* seen = actionToQueue(action);
142 
143   assert(action != PlaceholderTable::LOAD_INSTANCE || !EnableWaitForParallelLoad || seen == NULL,
144          "Only one LOAD_INSTANCE allowed at a time");
145 
146   if (seen == NULL) {
147     set_threadQ(threadEntry, action);

222 // Remove a placeholder object.
223 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
224   assert_locked_or_safepoint(SystemDictionary_lock);
225 
226   PlaceholderKey key(class_name, loader_data);
227   _placeholders.remove(key);
228 }
229 
230 
231 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
232   assert_locked_or_safepoint(SystemDictionary_lock);
233   PlaceholderKey key(class_name, loader_data);
234   return _placeholders.get(key);
235 }
236 
237 static const char* action_to_string(PlaceholderTable::classloadAction action) {
238   switch (action) {
239   case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
240   case PlaceholderTable::LOAD_SUPER:    return "LOAD_SUPER";
241   case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";
242   case PlaceholderTable::PRIMITIVE_OBJECT_FIELD: return "PRIMITIVE_OBJECT_FIELD";
243  }
244  return "";
245 }
246 
247 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
248   if (log_is_enabled(Debug, class, load, placeholders)) {
249     LogTarget(Debug, class, load, placeholders) lt;
250     ResourceMark rm;
251     LogStream ls(lt);
252     ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
253     entry->print_on(&ls);
254   }
255 }
256 
257 // find_and_add returns probe pointer - old or new
258 // If no entry exists, add a placeholder entry
259 // If entry exists, reuse entry
260 // For both, push SeenThread for classloadAction
261 // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
262 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,

286 // loadInstanceThreadQ tracks load_instance_class calls
287 // definer() tracks the single thread that owns define token
288 // defineThreadQ tracks waiters on defining thread's results
289 // 1st claimant creates placeholder
290 // find_and_add adds SeenThread entry for appropriate queue
291 // All claimants remove SeenThread after completing action
292 // On removal: if definer and all queues empty, remove entry
293 // Note: you can be in both placeholders and systemDictionary
294 // Therefore - must always check SD first
295 // Ignores the case where entry is not found
296 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
297                                        classloadAction action,
298                                        JavaThread* thread) {
299   assert_locked_or_safepoint(SystemDictionary_lock);
300   PlaceholderEntry* probe = get_entry(name, loader_data);
301   if (probe != NULL) {
302     log(name, probe, "find_and_remove", action);
303     probe->remove_seen_thread(thread, action);
304     // If no other threads using this entry, and this thread is not using this entry for other states
305     if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL)
306         && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)
307         && (probe->inlineTypeFieldQ() == NULL)) {
308       probe->clear_supername();
309       remove_entry(name, loader_data);
310     }
311   }
312 }
313 
314 void PlaceholderKey::print_on(outputStream* st) const {
315   _name->print_value_on(st);
316   st->print(", loader ");
317   _loader_data->print_value_on(st);
318 }
319 
320 void PlaceholderEntry::print_on(outputStream* st) const {
321   if (supername() != NULL) {
322     st->print(", supername ");
323     supername()->print_value_on(st);
324   }
325   if (definer() != NULL) {
326     st->print(", definer ");
327     definer()->print_value_on(st);
328   }
329   if (instance_klass() != NULL) {
330     st->print(", InstanceKlass ");
331     instance_klass()->print_value_on(st);
332   }
333   st->cr();
334   st->print("loadInstanceThreadQ threads:");
335   loadInstanceThreadQ()->print_action_queue(st);
336   st->cr();
337   st->print("superThreadQ threads:");
338   superThreadQ()->print_action_queue(st);
339   st->cr();
340   st->print("defineThreadQ threads:");
341   defineThreadQ()->print_action_queue(st);
342   st->cr();
343   st->print("inlineTypeFieldQ threads:");
344   inlineTypeFieldQ()->print_action_queue(st);
345   st->cr();
346 }
347 
348 void PlaceholderTable::print_on(outputStream* st) {
349   auto printer = [&] (PlaceholderKey& key, PlaceholderEntry& entry) {
350       st->print("placeholder ");
351       key.print_on(st);
352       entry.print_on(st);
353       return true;
354   };
355   st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
356                 _placeholders.table_size(), _placeholders.number_of_entries());
357   _placeholders.iterate(printer);
358 }
359 
360 void PlaceholderTable::print() { return print_on(tty); }
< prev index next >