< prev index next >

src/hotspot/share/opto/runtime.cpp

Print this page
*** 30,10 ***
--- 30,11 ---
  #include "code/nmethod.hpp"
  #include "code/pcDesc.hpp"
  #include "code/scopeDesc.hpp"
  #include "code/vtableStubs.hpp"
  #include "compiler/compileBroker.hpp"
+ #include "compiler/compilerDefinitions.inline.hpp"
  #include "compiler/oopMap.hpp"
  #include "gc/g1/g1HeapRegion.hpp"
  #include "gc/shared/barrierSet.hpp"
  #include "gc/shared/collectedHeap.hpp"
  #include "gc/shared/gcLocker.hpp"

*** 63,20 ***
--- 64,23 ---
  #include "prims/jvmtiExport.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
+ #include "runtime/java.hpp"
  #include "runtime/javaCalls.hpp"
+ #include "runtime/perfData.inline.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/signature.hpp"
  #include "runtime/stackWatermarkSet.hpp"
  #include "runtime/synchronizer.hpp"
  #include "runtime/threadCritical.hpp"
  #include "runtime/threadWXSetters.inline.hpp"
  #include "runtime/vframe.hpp"
  #include "runtime/vframeArray.hpp"
  #include "runtime/vframe_hp.hpp"
+ #include "services/management.hpp"
  #include "utilities/copy.hpp"
  #include "utilities/preserveException.hpp"
  
  
  // For debugging purposes:

*** 98,20 ***
--- 102,25 ---
  C2_STUBS_DO(C2_BLOB_FIELD_DEFINE, C2_STUB_FIELD_DEFINE, C2_JVMTI_STUB_FIELD_DEFINE)
  #undef C2_BLOB_FIELD_DEFINE
  #undef C2_STUB_FIELD_DEFINE
  #undef C2_JVMTI_STUB_FIELD_DEFINE
  
+ 
  #define C2_BLOB_NAME_DEFINE(name, type)  "C2 Runtime " # name "_blob",
  #define C2_STUB_NAME_DEFINE(name, f, t, r)  "C2 Runtime " # name,
  #define C2_JVMTI_STUB_NAME_DEFINE(name)  "C2 Runtime " # name,
  const char* OptoRuntime::_stub_names[] = {
    C2_STUBS_DO(C2_BLOB_NAME_DEFINE, C2_STUB_NAME_DEFINE, C2_JVMTI_STUB_NAME_DEFINE)
  };
  #undef C2_BLOB_NAME_DEFINE
  #undef C2_STUB_NAME_DEFINE
  #undef C2_JVMTI_STUB_NAME_DEFINE
  
+ address OptoRuntime::_vtable_must_compile_Java                    = nullptr;
+ 
+ PerfCounter* _perf_OptoRuntime_class_init_barrier_redundant_count = nullptr;
+ 
  // This should be called in an assertion at the start of OptoRuntime routines
  // which are entered from compiled code (all of them)
  #ifdef ASSERT
  static bool check_compiled_frame(JavaThread* thread) {
    assert(thread->last_frame().is_runtime_frame(), "cannot call runtime directly from compiled code");

*** 172,10 ***
--- 181,11 ---
                    true,                                                 \
                    false);                                               \
    if (STUB_FIELD_NAME(name) == nullptr) { return false; }               \
  
  bool OptoRuntime::generate(ciEnv* env) {
+   init_counters();
  
    C2_STUBS_DO(GEN_C2_BLOB, GEN_C2_STUB, GEN_C2_JVMTI_STUB)
  
    return true;
  }

*** 199,11 ***
                                     const char *name, int is_fancy_jump,
                                     bool pass_tls,
                                     bool return_pc) {
  
    // Matching the default directive, we currently have no method to match.
!   DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
    ResourceMark rm;
    Compile C(env, gen, C_function, name, is_fancy_jump, pass_tls, return_pc, directive);
    DirectivesStack::release(directive);
    return  C.stub_entry_point();
  }
--- 209,11 ---
                                     const char *name, int is_fancy_jump,
                                     bool pass_tls,
                                     bool return_pc) {
  
    // Matching the default directive, we currently have no method to match.
!   DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompilerThread::current()->compiler());
    ResourceMark rm;
    Compile C(env, gen, C_function, name, is_fancy_jump, pass_tls, return_pc, directive);
    DirectivesStack::release(directive);
    return  C.stub_entry_point();
  }

*** 242,11 ***
  //=============================allocation======================================
  // We failed the fast-path allocation.  Now we need to do a scavenge or GC
  // and try allocation again.
  
  // object allocation
! JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_instance_ctr++;         // new instance requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
--- 252,11 ---
  //=============================allocation======================================
  // We failed the fast-path allocation.  Now we need to do a scavenge or GC
  // and try allocation again.
  
  // object allocation
! JRT_BLOCK_ENTRY_PROF(void, OptoRuntime, new_instance_C, OptoRuntime::new_instance_C(Klass* klass, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_instance_ctr++;         // new instance requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");

*** 280,11 ***
    SharedRuntime::on_slowpath_allocation_exit(current);
  JRT_END
  
  
  // array allocation
! JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_array_ctr++;            // new array requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
--- 290,11 ---
    SharedRuntime::on_slowpath_allocation_exit(current);
  JRT_END
  
  
  // array allocation
! JRT_BLOCK_ENTRY_PROF(void, OptoRuntime, new_array_C, OptoRuntime::new_array_C(Klass* array_type, int len, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_array_ctr++;            // new array requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");

*** 317,11 ***
    // inform GC that we won't do card marks for initializing writes.
    SharedRuntime::on_slowpath_allocation_exit(current);
  JRT_END
  
  // array allocation without zeroing
! JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_array_ctr++;            // new array requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
--- 327,11 ---
    // inform GC that we won't do card marks for initializing writes.
    SharedRuntime::on_slowpath_allocation_exit(current);
  JRT_END
  
  // array allocation without zeroing
! JRT_BLOCK_ENTRY_PROF(void, OptoRuntime, new_array_nozero_C, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread* current))
    JRT_BLOCK;
  #ifndef PRODUCT
    SharedRuntime::_new_array_ctr++;            // new array requires GC
  #endif
    assert(check_compiled_frame(current), "incorrect caller");

*** 369,11 ***
  JRT_END
  
  // Note: multianewarray for one dimension is handled inline by GraphKit::new_array.
  
  // multianewarray for 2 dimensions
! JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int len2, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi2_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");
--- 379,11 ---
  JRT_END
  
  // Note: multianewarray for one dimension is handled inline by GraphKit::new_array.
  
  // multianewarray for 2 dimensions
! JRT_ENTRY_PROF(void, OptoRuntime, multianewarray2_C, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int len2, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi2_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");

*** 385,11 ***
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
  // multianewarray for 3 dimensions
! JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int len2, int len3, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi3_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");
--- 395,11 ---
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
  // multianewarray for 3 dimensions
! JRT_ENTRY_PROF(void, OptoRuntime, multianewarray3_C, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int len2, int len3, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi3_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");

*** 402,11 ***
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
  // multianewarray for 4 dimensions
! JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int len2, int len3, int len4, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi4_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");
--- 412,11 ---
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
  // multianewarray for 4 dimensions
! JRT_ENTRY_PROF(void, OptoRuntime, multianewarray4_C, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int len2, int len3, int len4, JavaThread* current))
  #ifndef PRODUCT
    SharedRuntime::_multi4_ctr++;                // multianewarray for 1 dimension
  #endif
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");

*** 438,11 ***
    oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD);
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
! JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* dims, JavaThread* current))
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");
    assert(oop(dims)->is_typeArray(), "not an array");
  
    ResourceMark rm;
--- 448,11 ---
    oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD);
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
! JRT_ENTRY_PROF(void, OptoRuntime, multianewarrayN_C, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* dims, JavaThread* current))
    assert(check_compiled_frame(current), "incorrect caller");
    assert(elem_type->is_klass(), "not a class");
    assert(oop(dims)->is_typeArray(), "not an array");
  
    ResourceMark rm;

*** 456,11 ***
    oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD);
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
! JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notify_C(oopDesc* obj, JavaThread* current))
  
    // Very few notify/notifyAll operations find any threads on the waitset, so
    // the dominant fast-path is to simply return.
    // Relatedly, it's critical that notify/notifyAll be fast in order to
    // reduce lock hold times.
--- 466,11 ---
    oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD);
    deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
    current->set_vm_result(obj);
  JRT_END
  
! JRT_BLOCK_ENTRY_PROF(void, OptoRuntime, monitor_notify_C, OptoRuntime::monitor_notify_C(oopDesc* obj, JavaThread* current))
  
    // Very few notify/notifyAll operations find any threads on the waitset, so
    // the dominant fast-path is to simply return.
    // Relatedly, it's critical that notify/notifyAll be fast in order to
    // reduce lock hold times.

*** 478,11 ***
    Handle h_obj(current, obj);
    ObjectSynchronizer::notify(h_obj, CHECK);
    JRT_BLOCK_END;
  JRT_END
  
! JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notifyAll_C(oopDesc* obj, JavaThread* current))
  
    if (!SafepointSynchronize::is_synchronizing() ) {
      if (ObjectSynchronizer::quick_notify(obj, current, true)) {
        return;
      }
--- 488,11 ---
    Handle h_obj(current, obj);
    ObjectSynchronizer::notify(h_obj, CHECK);
    JRT_BLOCK_END;
  JRT_END
  
! JRT_BLOCK_ENTRY_PROF(void, OptoRuntime, monitor_notifyAll_C, OptoRuntime::monitor_notifyAll_C(oopDesc* obj, JavaThread* current))
  
    if (!SafepointSynchronize::is_synchronizing() ) {
      if (ObjectSynchronizer::quick_notify(obj, current, true)) {
        return;
      }

*** 1542,11 ***
  static void trace_exception(outputStream* st, oop exception_oop, address exception_pc, const char* msg);
  
  // The method is an entry that is always called by a C++ method not
  // directly from compiled code. Compiled code will call the C++ method following.
  // We can't allow async exception to be installed during  exception processing.
! JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* current, nmethod* &nm))
    // The frame we rethrow the exception to might not have been processed by the GC yet.
    // The stack watermark barrier takes care of detecting that and ensuring the frame
    // has updated oops.
    StackWatermarkSet::after_unwind(current);
  
--- 1552,11 ---
  static void trace_exception(outputStream* st, oop exception_oop, address exception_pc, const char* msg);
  
  // The method is an entry that is always called by a C++ method not
  // directly from compiled code. Compiled code will call the C++ method following.
  // We can't allow async exception to be installed during  exception processing.
! JRT_ENTRY_NO_ASYNC_PROF(address, OptoRuntime, handle_exception_C_helper, OptoRuntime::handle_exception_C_helper(JavaThread* current, nmethod* &nm))
    // The frame we rethrow the exception to might not have been processed by the GC yet.
    // The stack watermark barrier takes care of detecting that and ensuring the frame
    // has updated oops.
    StackWatermarkSet::after_unwind(current);
  

*** 1818,10 ***
--- 1828,24 ---
    const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
  
    return TypeFunc::make(domain,range);
  }
  
+ const TypeFunc *OptoRuntime::class_init_barrier_Type() {
+   // create input type (domain)
+   const Type** fields = TypeTuple::fields(1);
+   fields[TypeFunc::Parms+0] = TypeKlassPtr::NOTNULL;
+   // // The JavaThread* is passed to each routine as the last argument
+   // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL;  // JavaThread *; Executing thread
+   const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+1, fields);
+ 
+   // create result type (range)
+   fields = TypeTuple::fields(0);
+   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
+   return TypeFunc::make(domain,range);
+ }
+ 
  #if INCLUDE_JFR
  const TypeFunc *OptoRuntime::class_id_load_barrier_Type() {
    // create input type (domain)
    const Type **fields = TypeTuple::fields(1);
    fields[TypeFunc::Parms+0] = TypeInstPtr::KLASS;

*** 1834,10 ***
--- 1858,26 ---
  
    return TypeFunc::make(domain,range);
  }
  #endif
  
+ //-----------------------------------------------------------------------------
+ // runtime upcall support
+ const TypeFunc *OptoRuntime::runtime_up_call_Type() {
+   // create input type (domain)
+   const Type **fields = TypeTuple::fields(1);
+   fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage
+   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields);
+ 
+   // create result type (range)
+   fields = TypeTuple::fields(0);
+ 
+   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
+ 
+   return TypeFunc::make(domain,range);
+ }
+ 
  //-----------------------------------------------------------------------------
  // Dtrace support.  entry and exit probes have the same signature
  const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() {
    // create input type (domain)
    const Type **fields = TypeTuple::fields(2);

*** 1868,16 ***
  
    return TypeFunc::make(domain,range);
  }
  
  
! JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer_C(oopDesc* obj, JavaThread* current))
    assert(oopDesc::is_oop(obj), "must be a valid oop");
    assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
    InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
  JRT_END
  
  //-----------------------------------------------------------------------------
  
  NamedCounter * volatile OptoRuntime::_named_counters = nullptr;
  
  //
--- 1908,25 ---
  
    return TypeFunc::make(domain,range);
  }
  
  
! JRT_ENTRY_NO_ASYNC_PROF(void, OptoRuntime, register_finalizer_C, OptoRuntime::register_finalizer_C(oopDesc* obj, JavaThread* current))
    assert(oopDesc::is_oop(obj), "must be a valid oop");
    assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
    InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
  JRT_END
  
+ JRT_ENTRY_NO_ASYNC_PROF(void, OptoRuntime, class_init_barrier_C, OptoRuntime::class_init_barrier_C(Klass* k, JavaThread* current))
+   InstanceKlass* ik = InstanceKlass::cast(k);
+   if (ik->should_be_initialized()) {
+     ik->initialize(CHECK);
+   } else if (UsePerfData) {
+     _perf_OptoRuntime_class_init_barrier_redundant_count->inc();
+   }
+ JRT_END
+ 
  //-----------------------------------------------------------------------------
  
  NamedCounter * volatile OptoRuntime::_named_counters = nullptr;
  
  //

*** 1974,5 ***
--- 2023,71 ---
    tempst.print(" at " INTPTR_FORMAT,  p2i(exception_pc));
    tempst.print("]");
  
    st->print_raw_cr(tempst.freeze());
  }
+ 
+ #define DO_COUNTERS2(macro2, macro1) \
+   macro2(OptoRuntime, new_instance_C) \
+   macro2(OptoRuntime, new_array_C) \
+   macro2(OptoRuntime, new_array_nozero_C) \
+   macro2(OptoRuntime, multianewarray2_C) \
+   macro2(OptoRuntime, multianewarray3_C) \
+   macro2(OptoRuntime, multianewarray4_C) \
+   macro2(OptoRuntime, multianewarrayN_C) \
+   macro2(OptoRuntime, monitor_notify_C) \
+   macro2(OptoRuntime, monitor_notifyAll_C) \
+   macro2(OptoRuntime, handle_exception_C_helper) \
+   macro2(OptoRuntime, register_finalizer_C) \
+   macro2(OptoRuntime, class_init_barrier_C) \
+   macro1(OptoRuntime, class_init_barrier_redundant)
+ 
+ #define INIT_COUNTER_TIME_AND_CNT(sub, name) \
+   NEWPERFTICKCOUNTERS(_perf_##sub##_##name##_timer, SUN_CI, #sub "::" #name); \
+   NEWPERFEVENTCOUNTER(_perf_##sub##_##name##_count, SUN_CI, #sub "::" #name "_count");
+ 
+ #define INIT_COUNTER_CNT(sub, name) \
+   NEWPERFEVENTCOUNTER(_perf_##sub##_##name##_count, SUN_CI, #sub "::" #name "_count");
+ 
+ void OptoRuntime::init_counters() {
+   assert(CompilerConfig::is_c2_enabled(), "");
+ 
+   if (UsePerfData) {
+     EXCEPTION_MARK;
+ 
+     DO_COUNTERS2(INIT_COUNTER_TIME_AND_CNT, INIT_COUNTER_CNT)
+ 
+     if (HAS_PENDING_EXCEPTION) {
+       vm_exit_during_initialization("jvm_perf_init failed unexpectedly");
+     }
+   }
+ }
+ #undef INIT_COUNTER_TIME_AND_CNT
+ #undef INIT_COUNTER_CNT
+ 
+ #define PRINT_COUNTER_TIME_AND_CNT(sub, name) { \
+   jlong count = _perf_##sub##_##name##_count->get_value(); \
+   if (count > 0) { \
+     st->print_cr("  %-50s = " JLONG_FORMAT_W(6) "us (elapsed) " JLONG_FORMAT_W(6) "us (thread) (" JLONG_FORMAT_W(5) " events)", #sub "::" #name, \
+                  _perf_##sub##_##name##_timer->elapsed_counter_value_us(), \
+                  _perf_##sub##_##name##_timer->thread_counter_value_us(), \
+                  count); \
+   }}
+ 
+ #define PRINT_COUNTER_CNT(sub, name) { \
+   jlong count = _perf_##sub##_##name##_count->get_value(); \
+   if (count > 0) { \
+     st->print_cr("  %-30s = " JLONG_FORMAT_W(5) " events", #name, count); \
+   }}
+ 
+ void OptoRuntime::print_counters_on(outputStream* st) {
+   if (UsePerfData && ProfileRuntimeCalls && CompilerConfig::is_c2_enabled()) {
+     DO_COUNTERS2(PRINT_COUNTER_TIME_AND_CNT, PRINT_COUNTER_CNT)
+   } else {
+     st->print_cr("  OptoRuntime: no info (%s is disabled)",
+                  (!CompilerConfig::is_c2_enabled() ? "C2" : (UsePerfData ? "ProfileRuntimeCalls" : "UsePerfData")));
+   }
+ }
+ 
+ #undef PRINT_COUNTER_TIME_AND_CNT
+ #undef PRINT_COUNTER_CNT
+ #undef DO_COUNTERS2
< prev index next >