< prev index next >

src/hotspot/share/classfile/placeholders.cpp

Print this page
*** 60,10 ***
--- 60,12 ---
  // For bootclasssearchpath, set before calling load_instance_class.
  // Defining must be single threaded on a class/classloader basis
  // For DEFINE_CLASS, the head of the queue owns the
  // define token and the rest of the threads wait to return the
  // result the first thread gets.
+ // For INLINE_FIELD, set when loading inline type fields for
+ // class circularity checking.
  class SeenThread: public CHeapObj<mtInternal> {
  private:
     JavaThread* _thread;
     SeenThread* _stnext;
     SeenThread* _stprev;

*** 93,12 ***
    SeenThread* queuehead = nullptr;
    switch (action) {
      case PlaceholderTable::LOAD_INSTANCE:
         queuehead = _loadInstanceThreadQ;
         break;
!     case PlaceholderTable::LOAD_SUPER:
!        queuehead = _superThreadQ;
         break;
      case PlaceholderTable::DEFINE_CLASS:
         queuehead = _defineThreadQ;
         break;
      default: Unimplemented();
--- 95,12 ---
    SeenThread* queuehead = nullptr;
    switch (action) {
      case PlaceholderTable::LOAD_INSTANCE:
         queuehead = _loadInstanceThreadQ;
         break;
!     case PlaceholderTable::DETECT_CIRCULARITY:
!        queuehead = _circularityThreadQ;
         break;
      case PlaceholderTable::DEFINE_CLASS:
         queuehead = _defineThreadQ;
         break;
      default: Unimplemented();

*** 109,12 ***
  void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
    switch (action) {
      case PlaceholderTable::LOAD_INSTANCE:
         _loadInstanceThreadQ = seenthread;
         break;
!     case PlaceholderTable::LOAD_SUPER:
!        _superThreadQ = seenthread;
         break;
      case PlaceholderTable::DEFINE_CLASS:
         _defineThreadQ = seenthread;
         break;
      default: Unimplemented();
--- 111,12 ---
  void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
    switch (action) {
      case PlaceholderTable::LOAD_INSTANCE:
         _loadInstanceThreadQ = seenthread;
         break;
!     case PlaceholderTable::DETECT_CIRCULARITY:
!        _circularityThreadQ = seenthread;
         break;
      case PlaceholderTable::DEFINE_CLASS:
         _defineThreadQ = seenthread;
         break;
      default: Unimplemented();

*** 186,27 ***
    }
    return (actionToQueue(action) == nullptr);
  }
  
  
! void PlaceholderEntry::set_supername(Symbol* supername) {
    assert_locked_or_safepoint(SystemDictionary_lock);
!   assert(_supername == nullptr || _supername->refcount() > 1, "must be referenced also by the loader");
!   _supername = supername;
  }
  
  // Placeholder objects represent classes currently being loaded.
  // All threads examining the placeholder table must hold the
  // SystemDictionary_lock, so we don't need special precautions
  // on store ordering here.
  PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
!                             Symbol* supername){
    assert_locked_or_safepoint(SystemDictionary_lock);
    assert(class_name != nullptr, "adding nullptr obj");
  
    PlaceholderEntry entry;
!   entry.set_supername(supername);
    PlaceholderKey key(class_name, loader_data);
    bool created;
    PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
    assert(created, "better be absent");
    return table_copy;
--- 188,27 ---
    }
    return (actionToQueue(action) == nullptr);
  }
  
  
! void PlaceholderEntry::set_next_klass_name(Symbol* next_klass_name) {
    assert_locked_or_safepoint(SystemDictionary_lock);
!   assert(_next_klass_name == nullptr || _next_klass_name->refcount() > 1, "must be referenced also by the loader");
!   _next_klass_name = next_klass_name;
  }
  
  // Placeholder objects represent classes currently being loaded.
  // All threads examining the placeholder table must hold the
  // SystemDictionary_lock, so we don't need special precautions
  // on store ordering here.
  PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
!                             Symbol* next_klass_name){
    assert_locked_or_safepoint(SystemDictionary_lock);
    assert(class_name != nullptr, "adding nullptr obj");
  
    PlaceholderEntry entry;
!   entry.set_next_klass_name(next_klass_name);
    PlaceholderKey key(class_name, loader_data);
    bool created;
    PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
    assert(created, "better be absent");
    return table_copy;

*** 228,11 ***
  }
  
  static const char* action_to_string(PlaceholderTable::classloadAction action) {
    switch (action) {
    case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
!   case PlaceholderTable::LOAD_SUPER:    return "LOAD_SUPER";
    case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";
   }
   return "";
  }
  
--- 230,11 ---
  }
  
  static const char* action_to_string(PlaceholderTable::classloadAction action) {
    switch (action) {
    case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
!   case PlaceholderTable::DETECT_CIRCULARITY:    return "DETECT_CIRCULARITY";
    case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";
   }
   return "";
  }
  

*** 248,24 ***
  
  // find_and_add returns probe pointer - old or new
  // If no entry exists, add a placeholder entry
  // If entry exists, reuse entry
  // For both, push SeenThread for classloadAction
! // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
  PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
                                                   ClassLoaderData* loader_data,
                                                   classloadAction action,
!                                                  Symbol* supername,
                                                   JavaThread* thread) {
!   assert(action != LOAD_SUPER || supername != nullptr, "must have a super class name");
    PlaceholderEntry* probe = get_entry(name, loader_data);
    if (probe == nullptr) {
      // Nothing found, add place holder
!     probe = add_entry(name, loader_data, supername);
    } else {
!     if (action == LOAD_SUPER) {
!       probe->set_supername(supername);
      }
    }
    probe->add_seen_thread(thread, action);
    log(name, probe, "find_and_add", action);
    return probe;
--- 250,24 ---
  
  // find_and_add returns probe pointer - old or new
  // If no entry exists, add a placeholder entry
  // If entry exists, reuse entry
  // For both, push SeenThread for classloadAction
! // If DETECT_CIRCULARITY, this is used for circularity detection for instanceklass loading.
  PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
                                                   ClassLoaderData* loader_data,
                                                   classloadAction action,
!                                                  Symbol* next_klass_name,
                                                   JavaThread* thread) {
!   assert(action != DETECT_CIRCULARITY || next_klass_name != nullptr, "must have a super class name");
    PlaceholderEntry* probe = get_entry(name, loader_data);
    if (probe == nullptr) {
      // Nothing found, add place holder
!     probe = add_entry(name, loader_data, next_klass_name);
    } else {
!     if (action == DETECT_CIRCULARITY) {
!       probe->set_next_klass_name(next_klass_name);
      }
    }
    probe->add_seen_thread(thread, action);
    log(name, probe, "find_and_add", action);
    return probe;

*** 294,11 ***
    PlaceholderEntry* probe = get_entry(name, loader_data);
    assert(probe != nullptr, "must find an entry");
    log(name, probe, "find_and_remove", action);
    probe->remove_seen_thread(thread, action);
    if (probe->superThreadQ() == nullptr) {
!     probe->set_supername(nullptr);
    }
    // If no other threads using this entry, and this thread is not using this entry for other states
    if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
        && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
      remove_entry(name, loader_data);
--- 296,11 ---
    PlaceholderEntry* probe = get_entry(name, loader_data);
    assert(probe != nullptr, "must find an entry");
    log(name, probe, "find_and_remove", action);
    probe->remove_seen_thread(thread, action);
    if (probe->superThreadQ() == nullptr) {
!     probe->set_next_klass_name(nullptr);
    }
    // If no other threads using this entry, and this thread is not using this entry for other states
    if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
        && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
      remove_entry(name, loader_data);

*** 310,13 ***
    st->print(", loader ");
    _loader_data->print_value_on(st);
  }
  
  void PlaceholderEntry::print_on(outputStream* st) const {
!   if (supername() != nullptr) {
!     st->print(", supername ");
!     supername()->print_value_on(st);
    }
    if (definer() != nullptr) {
      st->print(", definer ");
      definer()->print_value_on(st);
    }
--- 312,13 ---
    st->print(", loader ");
    _loader_data->print_value_on(st);
  }
  
  void PlaceholderEntry::print_on(outputStream* st) const {
!   if (next_klass_name() != nullptr) {
!     st->print(", next_klass_name ");
!     next_klass_name()->print_value_on(st);
    }
    if (definer() != nullptr) {
      st->print(", definer ");
      definer()->print_value_on(st);
    }
< prev index next >