< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page
*** 21,10 ***
--- 21,11 ---
   * questions.
   *
   */
  
  #include "cds/aotClassInitializer.hpp"
+ #include "cds/aotLinkedClassBulkLoader.hpp"
  #include "cds/aotMetaspace.hpp"
  #include "cds/archiveUtils.hpp"
  #include "cds/cdsConfig.hpp"
  #include "cds/cdsEnumKlass.hpp"
  #include "cds/classListWriter.hpp"

*** 43,10 ***
--- 44,11 ---
  #include "code/codeCache.hpp"
  #include "code/dependencyContext.hpp"
  #include "compiler/compilationPolicy.hpp"
  #include "compiler/compileBroker.hpp"
  #include "gc/shared/collectedHeap.inline.hpp"
+ #include "interpreter/bytecodeHistogram.hpp"
  #include "interpreter/bytecodeStream.hpp"
  #include "interpreter/oopMapCache.hpp"
  #include "interpreter/rewriter.hpp"
  #include "jvm.h"
  #include "jvmtifiles/jvmti.h"

*** 86,10 ***
--- 88,11 ---
  #include "runtime/javaThread.inline.hpp"
  #include "runtime/mutexLocker.hpp"
  #include "runtime/orderAccess.hpp"
  #include "runtime/os.inline.hpp"
  #include "runtime/reflection.hpp"
+ #include "runtime/runtimeUpcalls.hpp"
  #include "runtime/synchronizer.hpp"
  #include "runtime/threads.hpp"
  #include "services/classLoadingService.hpp"
  #include "services/finalizerService.hpp"
  #include "services/threadService.hpp"

*** 148,10 ***
--- 151,11 ---
  #define DTRACE_CLASSINIT_PROBE_WAIT(type, thread_type, wait)
  
  #endif //  ndef DTRACE_ENABLED
  
  bool InstanceKlass::_finalization_enabled = true;
+ static int call_class_initializer_counter = 0;   // for debugging
  
  static inline bool is_class_loader(const Symbol* class_name,
                                     const ClassFileParser& parser) {
    assert(class_name != nullptr, "invariant");
  

*** 882,29 ***
    }
  }
  #endif
  
  #if INCLUDE_CDS
! void InstanceKlass::initialize_with_aot_initialized_mirror(TRAPS) {
    assert(has_aot_initialized_mirror(), "must be");
    assert(CDSConfig::is_loading_heap(), "must be");
    assert(CDSConfig::is_using_aot_linked_classes(), "must be");
    assert_no_clinit_will_run_for_aot_initialized_class();
  
    if (is_initialized()) {
      return;
    }
  
    if (is_runtime_setup_required()) {
      // Need to take the slow path, which will call the runtimeSetup() function instead
      // of <clinit>
      initialize(CHECK);
      return;
    }
!   if (log_is_enabled(Info, aot, init)) {
!     ResourceMark rm;
!     log_info(aot, init)("%s (aot-inited)", external_name());
    }
  
    link_class(CHECK);
  
  #ifdef ASSERT
--- 886,52 ---
    }
  }
  #endif
  
  #if INCLUDE_CDS
! // early_init -- we are moving this class into the fully_initialized state before the
+ // JVM is able to execute any bytecodes. See AOTLinkedClassBulkLoader::is_initializing_classes_early().
+ void InstanceKlass::initialize_with_aot_initialized_mirror(bool early_init, TRAPS) {
    assert(has_aot_initialized_mirror(), "must be");
    assert(CDSConfig::is_loading_heap(), "must be");
    assert(CDSConfig::is_using_aot_linked_classes(), "must be");
    assert_no_clinit_will_run_for_aot_initialized_class();
  
    if (is_initialized()) {
      return;
    }
  
+   if (log_is_enabled(Info, aot, init)) {
+     ResourceMark rm;
+     log_info(aot, init)("%s (aot-inited%s)", external_name(), early_init ? ", early" : "");
+   }
+ 
    if (is_runtime_setup_required()) {
+     assert(!early_init, "must not call");
      // Need to take the slow path, which will call the runtimeSetup() function instead
      // of <clinit>
      initialize(CHECK);
      return;
    }
! 
!   LogTarget(Info, class, init) lt;
!   if (lt.is_enabled()) {
+     ResourceMark rm(THREAD);
+     LogStream ls(lt);
+     ls.print("%d Initializing ", call_class_initializer_counter++);
+     name()->print_value_on(&ls);
+     ls.print_cr("(aot-inited) (" PTR_FORMAT ") by thread \"%s\"",
+                 p2i(this), THREAD->name());
+   }
+ 
+   if (early_init) {
+     precond(AOTLinkedClassBulkLoader::is_initializing_classes_early());
+     precond(is_linked());
+     precond(init_thread() == nullptr);
+     set_init_state(fully_initialized);
+     fence_and_clear_init_lock();
+     return;
    }
  
    link_class(CHECK);
  
  #ifdef ASSERT

*** 1116,15 ***
  
  // Now relocate and link method entry points after class is rewritten.
  // This is outside is_rewritten flag. In case of an exception, it can be
  // executed more than once.
  void InstanceKlass::link_methods(TRAPS) {
!   PerfTraceTime timer(ClassLoader::perf_ik_link_methods_time());
  
    int len = methods()->length();
    for (int i = len-1; i >= 0; i--) {
      methodHandle m(THREAD, methods()->at(i));
  
      // Set up method entry points for compiler and interpreter    .
      m->link_method(m, CHECK);
    }
  }
--- 1143,16 ---
  
  // Now relocate and link method entry points after class is rewritten.
  // This is outside is_rewritten flag. In case of an exception, it can be
  // executed more than once.
  void InstanceKlass::link_methods(TRAPS) {
!   PerfTraceElapsedTime timer(ClassLoader::perf_ik_link_methods_time());
  
    int len = methods()->length();
    for (int i = len-1; i >= 0; i--) {
      methodHandle m(THREAD, methods()->at(i));
+     RuntimeUpcalls::install_upcalls(m);
  
      // Set up method entry points for compiler and interpreter    .
      m->link_method(m, CHECK);
    }
  }

*** 1236,10 ***
--- 1264,25 ---
  
    bool wait = false;
  
    JavaThread* jt = THREAD;
  
+   if (ForceProfiling) {
+     // Preallocate MDOs.
+     for (int i = 0; i < methods()->length(); i++) {
+       assert(!HAS_PENDING_EXCEPTION, "");
+       methodHandle m(THREAD, methods()->at(i));
+       Method::build_profiling_method_data(m, THREAD);
+       if (HAS_PENDING_EXCEPTION) {
+         ResourceMark rm;
+         log_warning(cds)("MDO preallocation failed for %s", external_name());
+         CLEAR_PENDING_EXCEPTION;
+         break;
+       }
+     }
+   }
+ 
    bool debug_logging_enabled = log_is_enabled(Debug, class, init);
  
    // refer to the JVM book page 47 for description of steps
    // Step 1
    {

*** 1629,11 ***
    assert(!is_abstract() && !is_interface(), "Should not create this object");
    size_t size = size_helper();  // Query before forming handle.
    return (instanceOop)Universe::heap()->obj_allocate(this, size, CHECK_NULL);
  }
  
! instanceOop InstanceKlass::allocate_instance(oop java_class, TRAPS) {
    Klass* k = java_lang_Class::as_Klass(java_class);
    if (k == nullptr) {
      ResourceMark rm(THREAD);
      THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
    }
--- 1672,13 ---
    assert(!is_abstract() && !is_interface(), "Should not create this object");
    size_t size = size_helper();  // Query before forming handle.
    return (instanceOop)Universe::heap()->obj_allocate(this, size, CHECK_NULL);
  }
  
! instanceOop InstanceKlass::allocate_instance(oop java_class,
+                                              const char* who,
+                                              TRAPS) {
    Klass* k = java_lang_Class::as_Klass(java_class);
    if (k == nullptr) {
      ResourceMark rm(THREAD);
      THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
    }

*** 1697,12 ***
  
  ArrayKlass* InstanceKlass::array_klass_or_null() {
    return array_klass_or_null(1);
  }
  
- static int call_class_initializer_counter = 0;   // for debugging
- 
  Method* InstanceKlass::class_initializer() const {
    Method* clinit = find_method(
        vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());
    if (clinit != nullptr && clinit->has_valid_initializer_flags()) {
      return clinit;
--- 1742,10 ---

*** 1732,10 ***
--- 1775,64 ---
    }
  #endif
  
    methodHandle h_method(THREAD, class_initializer());
    assert(!is_initialized(), "we cannot initialize twice");
+ 
+ #if 0
+   // FIXME -- revive this code added to leyden/premain for <clinit> profiling
+   int init_id = log_class_init(THREAD, this);
+   if (h_method() != nullptr) {
+     JavaCallArguments args; // No arguments
+     JavaValue result(T_VOID);
+     InstanceKlass* outer = THREAD->set_class_being_initialized(this);
+     jlong bc_start = (CountBytecodesPerThread ? THREAD->bc_counter_value() : BytecodeCounter::counter_value());
+ 
+     elapsedTimer timer;
+     {
+       PerfPauseTimer pt(THREAD->current_rt_call_timer(), THREAD->profile_rt_calls());
+       PauseRuntimeCallProfiling prcp(THREAD, THREAD->profile_rt_calls());
+ 
+       timer.start();
+       JavaCalls::call(&result, h_method, &args, THREAD); // Static call (no args)
+       timer.stop();
+     }
+ 
+     jlong bc_end = (CountBytecodesPerThread ? THREAD->bc_counter_value() : BytecodeCounter::counter_value());
+ 
+     jlong bc_executed = (bc_end - bc_start);
+     if (UsePerfData && outer == nullptr) { // outermost clinit
+       THREAD->inc_clinit_bc_counter_value(bc_executed);
+       ClassLoader::perf_class_init_bytecodes_count()->inc(bc_executed);
+     }
+ 
+     THREAD->set_class_being_initialized(outer);
+ 
+     LogStreamHandle(Debug, init) log;
+     if (log.is_enabled()) {
+       ResourceMark rm(THREAD);
+       log.print("%d Initialized in %.3fms (total: " JLONG_FORMAT "ms); ",
+                 init_id, timer.seconds() * 1000.0, ClassLoader::class_init_time_ms());
+       if (CountBytecodes || CountBytecodesPerThread) {
+         log.print("executed " JLONG_FORMAT " bytecodes; ", bc_executed);
+       }
+       name()->print_value_on(&log);
+       log.print_cr(" by thread " PTR_FORMAT " \"%s\" (" PTR_FORMAT ")",
+                    p2i(THREAD), THREAD->name(), p2i(this));
+     }
+   }
+   LogTarget(Info, class, init) lt;
+   if (lt.is_enabled()) {
+     ResourceMark rm(THREAD);
+     LogStream ls(lt);
+     ls.print("%d Initialized ", init_id);
+     name()->print_value_on(&ls);
+     ls.print_cr("%s (" PTR_FORMAT ") by thread \"%s\"",
+                 h_method() == nullptr ? "(no method)" : "", p2i(this),
+                 THREAD->name());
+   }
+ #else
    LogTarget(Info, class, init) lt;
    if (lt.is_enabled()) {
      ResourceMark rm(THREAD);
      LogStream ls(lt);
      ls.print("%d Initializing ", call_class_initializer_counter++);

*** 1748,10 ***
--- 1845,11 ---
      ThreadInClassInitializer ticl(THREAD, this); // Track class being initialized
      JavaCallArguments args; // No arguments
      JavaValue result(T_VOID);
      JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
    }
+ #endif
  }
  
  // If a class that implements this interface is initialized, is the JVM required
  // to first execute a <clinit> method declared in this interface,
  // or (if also_check_supers==true) any of the super types of this interface?

*** 2556,11 ***
    DependencyContext dep_context(&_dep_context, &_dep_context_last_cleaned);
    return dep_context;
  }
  
  void InstanceKlass::mark_dependent_nmethods(DeoptimizationScope* deopt_scope, KlassDepChange& changes) {
!   dependencies().mark_dependent_nmethods(deopt_scope, changes);
  }
  
  void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
    assert_lock_strong(CodeCache_lock);
    dependencies().add_dependent_nmethod(nm);
--- 2654,11 ---
    DependencyContext dep_context(&_dep_context, &_dep_context_last_cleaned);
    return dep_context;
  }
  
  void InstanceKlass::mark_dependent_nmethods(DeoptimizationScope* deopt_scope, KlassDepChange& changes) {
!   dependencies().mark_dependent_nmethods(deopt_scope, changes, this);
  }
  
  void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
    assert_lock_strong(CodeCache_lock);
    dependencies().add_dependent_nmethod(nm);

*** 3672,10 ***
--- 3770,14 ---
  
  const char* InstanceKlass::init_state_name() const {
    return state_names[init_state()];
  }
  
+ const char* InstanceKlass::state2name(ClassState s) {
+   return state_names[s];
+ }
+ 
  void InstanceKlass::print_on(outputStream* st) const {
    assert(is_klass(), "must be klass");
    Klass::print_on(st);
  
    st->print(BULLET"instance size:     %d", size_helper());                        st->cr();

*** 4006,10 ***
--- 4108,30 ---
      } else {
        info_stream.print(" source: shared objects file");
      }
    }
  
+   info_stream.print(" loader:");
+ #if INCLUDE_CDS
+   if (in_aot_cache()) {
+     info_stream.print(" %s", SystemDictionaryShared::loader_type_for_shared_class((Klass*)this));
+   } else
+ #endif
+   if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
+     info_stream.print(" boot_loader");
+   } else {
+     oop class_loader = loader_data->class_loader();
+     if (class_loader != nullptr) {
+       info_stream.print(" %s", class_loader->klass()->external_name());
+       oop cl_name_and_id = java_lang_ClassLoader::nameAndId(class_loader);
+       if (cl_name_and_id != nullptr) {
+         info_stream.print(" %s", java_lang_String::as_utf8_string(cl_name_and_id));
+       }
+     } else {
+       info_stream.print(" null");
+     }
+   }
    msg.info("%s", info_stream.as_string());
  
    if (log_is_enabled(Debug, class, load)) {
      stringStream debug_stream;
  
< prev index next >