< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page
*** 792,22 ***
    assert(lock != nullptr || !is_not_initialized(), // initialized or in_error state
           "only fully initialized state can have a null lock");
    return lock;
  }
  
! // Set the initialization lock to null so the object can be GC'ed.  Any racing
! // threads to get this lock will see a null lock and will not lock.
! // That's okay because they all check for initialized state after getting
! // the lock and return.
! void InstanceKlass::fence_and_clear_init_lock() {
!   // make sure previous stores are all done, notably the init_state.
!   OrderAccess::storestore();
-   java_lang_Class::clear_init_lock(java_mirror());
-   assert(!is_not_initialized(), "class must be initialized now");
  }
  
- 
  // See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
  // process. The step comments refers to the procedure described in that section.
  // Note: implementation moved to static method to expose the this pointer.
  void InstanceKlass::initialize(TRAPS) {
    if (this->should_be_initialized()) {
--- 792,19 ---
    assert(lock != nullptr || !is_not_initialized(), // initialized or in_error state
           "only fully initialized state can have a null lock");
    return lock;
  }
  
! void InstanceKlass::initialize_preemptable(TRAPS) {
!   if (this->should_be_initialized()) {
!     PREEMPT_ON_INIT_SUPPORTED_ONLY(PreemptableInitCall pic(THREAD, this);)
!     initialize_impl(THREAD);
!   } else {
!     assert(is_initialized(), "sanity check");
!   }
  }
  
  // See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
  // process. The step comments refers to the procedure described in that section.
  // Note: implementation moved to static method to expose the this pointer.
  void InstanceKlass::initialize(TRAPS) {
    if (this->should_be_initialized()) {

*** 975,11 ***
  
    // verification & rewriting
    {
      HandleMark hm(THREAD);
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, jt);
      // rewritten will have been set if loader constraint error found
      // on an earlier link attempt
      // don't verify or rewrite if already rewritten
      //
  
--- 972,15 ---
  
    // verification & rewriting
    {
      HandleMark hm(THREAD);
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, CHECK_PREEMPTABLE_false);
+     // Don't preempt once we own the monitor as that would complicate
+     // redoing the VM call (we don't expect to own this monitor).
+     NoPreemptMark npm(THREAD);
+ 
      // rewritten will have been set if loader constraint error found
      // on an earlier link attempt
      // don't verify or rewrite if already rewritten
      //
  

*** 1188,11 ***
  
    // refer to the JVM book page 47 for description of steps
    // Step 1
    {
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, jt);
  
      // Step 2
      // If we were to use wait() instead of waitInterruptibly() then
      // we might end up throwing IE from link/symbol resolution sites
      // that aren't expected to throw.  This would wreak havoc.  See 6320309.
--- 1189,11 ---
  
    // refer to the JVM book page 47 for description of steps
    // Step 1
    {
      Handle h_init_lock(THREAD, init_lock());
!     ObjectLocker ol(h_init_lock, CHECK_PREEMPTABLE);
  
      // Step 2
      // If we were to use wait() instead of waitInterruptibly() then
      // we might end up throwing IE from link/symbol resolution sites
      // that aren't expected to throw.  This would wreak havoc.  See 6320309.

*** 1202,11 ***
          log_debug(class, init)("Thread \"%s\" waiting for initialization of %s by thread \"%s\"",
                                 jt->name(), external_name(), init_thread_name());
        }
        wait = true;
        jt->set_class_to_be_initialized(this);
!       ol.wait_uninterruptibly(jt);
        jt->set_class_to_be_initialized(nullptr);
      }
  
      // Step 3
      if (is_being_initialized() && is_reentrant_initialization(jt)) {
--- 1203,11 ---
          log_debug(class, init)("Thread \"%s\" waiting for initialization of %s by thread \"%s\"",
                                 jt->name(), external_name(), init_thread_name());
        }
        wait = true;
        jt->set_class_to_be_initialized(this);
!       ol.wait_uninterruptibly(CHECK_PREEMPTABLE);
        jt->set_class_to_be_initialized(nullptr);
      }
  
      // Step 3
      if (is_being_initialized() && is_reentrant_initialization(jt)) {

*** 1261,10 ***
--- 1262,14 ---
                                 jt->name(), external_name());
        }
      }
    }
  
+   // Block preemption once we are the initializer thread.
+   // Unmounting now would complicate the reentrant case.
+   NoPreemptMark npm(THREAD);
+ 
    // Step 7
    // Next, if C is a class rather than an interface, initialize it's super class and super
    // interfaces.
    if (!is_interface()) {
      Klass* super_klass = super();

*** 1357,11 ***
    Handle h_init_lock(THREAD, init_lock());
    if (h_init_lock() != nullptr) {
      ObjectLocker ol(h_init_lock, THREAD);
      set_init_thread(nullptr); // reset _init_thread before changing _init_state
      set_init_state(state);
-     fence_and_clear_init_lock();
      ol.notify_all(CHECK);
    } else {
      assert(h_init_lock() != nullptr, "The initialization state should never be set twice");
      set_init_thread(nullptr); // reset _init_thread before changing _init_state
      set_init_state(state);
--- 1362,10 ---
< prev index next >