< prev index next >

src/hotspot/share/c1/c1_Runtime1.cpp

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

@@ -37,10 +37,11 @@
  #include "code/compiledIC.hpp"
  #include "code/pcDesc.hpp"
  #include "code/scopeDesc.hpp"
  #include "code/vtableStubs.hpp"
  #include "compiler/compilationPolicy.hpp"
+ #include "compiler/compilerDefinitions.inline.hpp"
  #include "compiler/disassembler.hpp"
  #include "compiler/oopMap.hpp"
  #include "gc/shared/barrierSet.hpp"
  #include "gc/shared/c1/barrierSetC1.hpp"
  #include "gc/shared/collectedHeap.hpp"

@@ -62,17 +63,19 @@
  #include "runtime/fieldDescriptor.inline.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/javaCalls.hpp"
+ #include "runtime/perfData.inline.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/stackWatermarkSet.hpp"
  #include "runtime/stubRoutines.hpp"
  #include "runtime/threadCritical.hpp"
  #include "runtime/vframe.inline.hpp"
  #include "runtime/vframeArray.hpp"
  #include "runtime/vm_version.hpp"
+ #include "services/management.hpp"
  #include "utilities/copy.hpp"
  #include "utilities/events.hpp"
  
  
  // Implementation of StubAssembler

@@ -260,10 +263,11 @@
    // install blob
    _blobs[id] = blob;
  }
  
  void Runtime1::initialize(BufferBlob* blob) {
+   init_counters();
    // platform-dependent initialization
    initialize_pd();
    // generate stubs
    for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id);
    // printing

@@ -347,11 +351,11 @@
    // Soft float adds more runtime names.
    return pd_name_for_address(entry);
  }
  
  
- JRT_ENTRY(void, Runtime1::new_instance(JavaThread* current, Klass* klass))
+ JRT_ENTRY_PROF(void, Runtime1, new_instance, Runtime1::new_instance(JavaThread* current, Klass* klass))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_instance_slowcase_cnt++;
    }
  #endif

@@ -365,11 +369,11 @@
    oop obj = h->allocate_instance(CHECK);
    current->set_vm_result(obj);
  JRT_END
  
  
- JRT_ENTRY(void, Runtime1::new_type_array(JavaThread* current, Klass* klass, jint length))
+ JRT_ENTRY_PROF(void, Runtime1, new_type_array, Runtime1::new_type_array(JavaThread* current, Klass* klass, jint length))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_type_array_slowcase_cnt++;
    }
  #endif

@@ -387,11 +391,11 @@
    }
  
  JRT_END
  
  
- JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* current, Klass* array_klass, jint length))
+ JRT_ENTRY_PROF(void, Runtime1, new_object_array, Runtime1::new_object_array(JavaThread* current, Klass* array_klass, jint length))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_object_array_slowcase_cnt++;
    }
  #endif

@@ -409,11 +413,11 @@
      deopt_caller(current);
    }
  JRT_END
  
  
- JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims))
+ JRT_ENTRY_PROF(void, Runtime1, new_multi_array, Runtime1::new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_multi_array_slowcase_cnt++;
    }
  #endif

@@ -480,11 +484,11 @@
    }
    osr_nm = CompilationPolicy::event(enclosing_method, method, branch_bci, bci, level, nm, current);
    return osr_nm;
  }
  
- JRT_BLOCK_ENTRY(address, Runtime1::counter_overflow(JavaThread* current, int bci, Method* method))
+ JRT_BLOCK_ENTRY_PROF(address, Runtime1, counter_overflow, Runtime1::counter_overflow(JavaThread* current, int bci, Method* method))
    nmethod* osr_nm;
    JRT_BLOCK
      osr_nm = counter_overflow_helper(current, bci, method);
      if (osr_nm != nullptr) {
        RegisterMap map(current,

@@ -514,11 +518,11 @@
  // control the area where we can allow a safepoint. After we exit the safepoint area we can
  // check to see if the handler we are going to return is now in a nmethod that has
  // been deoptimized. If that is the case we return the deopt blob
  // unpack_with_exception entry instead. This makes life for the exception blob easier
  // because making that same check and diverting is painful from assembly language.
- JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm))
+ JRT_ENTRY_NO_ASYNC_PROF(static address, Runtime1, exception_handler_for_pc_helper, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm))
    // Reset method handle flag.
    current->set_is_method_handle_return(false);
  
    Handle exception(current, ex);
  

@@ -746,11 +750,11 @@
    ResourceMark rm(current);
    SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IncompatibleClassChangeError());
  JRT_END
  
  
- JRT_BLOCK_ENTRY(void, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, BasicObjectLock* lock))
+ JRT_BLOCK_ENTRY_PROF(void, Runtime1, monitorenter, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, BasicObjectLock* lock))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _monitorenter_slowcase_cnt++;
    }
  #endif

@@ -760,11 +764,11 @@
    assert(LockingMode == LM_LIGHTWEIGHT || obj == lock->obj(), "must match");
    SharedRuntime::monitor_enter_helper(obj, LockingMode == LM_LIGHTWEIGHT ? nullptr : lock->lock(), current);
  JRT_END
  
  
- JRT_LEAF(void, Runtime1::monitorexit(JavaThread* current, BasicObjectLock* lock))
+ JRT_LEAF_PROF(void, Runtime1, monitorexit, Runtime1::monitorexit(JavaThread* current, BasicObjectLock* lock))
    assert(current == JavaThread::current(), "pre-condition");
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _monitorexit_slowcase_cnt++;
    }

@@ -774,11 +778,11 @@
    assert(oopDesc::is_oop(obj), "must be null or an object");
    SharedRuntime::monitor_exit_helper(obj, lock->lock(), current);
  JRT_END
  
  // Cf. OptoRuntime::deoptimize_caller_frame
- JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request))
+ JRT_ENTRY_PROF(void, Runtime1, deoptimize, Runtime1::deoptimize(JavaThread* current, jint trap_request))
    // Called from within the owner thread, so no need for safepoint
    RegisterMap reg_map(current,
                        RegisterMap::UpdateMap::skip,
                        RegisterMap::ProcessFrames::include,
                        RegisterMap::WalkContinuation::skip);

@@ -817,11 +821,12 @@
    Bytecodes::Code code       = field_access.code();
  
    // We must load class, initialize class and resolve the field
    fieldDescriptor result; // initialize class if needed
    constantPoolHandle constants(THREAD, caller->constants());
-   LinkResolver::resolve_field_access(result, constants, field_access.index(), caller, Bytecodes::java_code(code), CHECK_NULL);
+   LinkResolver::resolve_field_access(result, constants, field_access.index(), caller,
+                                      Bytecodes::java_code(code), true /*initialize_class*/, CHECK_NULL);
    return result.field_holder();
  }
  
  
  //

@@ -920,11 +925,11 @@
  // but we don't want to bet the farm on this always working.
  //
  // Therefore, if there is any chance of a race condition, we try to
  // patch only naturally aligned words, as single, full-word writes.
  
- JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id ))
+ JRT_ENTRY_PROF(void, Runtime1, patch_code, Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _patch_code_slowcase_cnt++;
    }
  #endif

@@ -965,11 +970,12 @@
  
      Bytecode_field field_access(caller_method, bci);
      fieldDescriptor result; // initialize class if needed
      Bytecodes::Code code = field_access.code();
      constantPoolHandle constants(current, caller_method->constants());
-     LinkResolver::resolve_field_access(result, constants, field_access.index(), caller_method, Bytecodes::java_code(code), CHECK);
+     LinkResolver::resolve_field_access(result, constants, field_access.index(), caller_method,
+                                        Bytecodes::java_code(code), true /*initialize_class*/, CHECK);
      patch_field_offset = result.offset();
  
      // If we're patching a field which is volatile then at compile it
      // must not have been know to be volatile, so the generated code
      // isn't correct for a volatile reference.  The nmethod has to be

@@ -1308,11 +1314,11 @@
      }
    }
    return true;
  }
  
- void Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id) {
+ PROF_ENTRY(void, Runtime1, patch_code, Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _patch_code_slowcase_cnt++;
    }
  #endif

@@ -1343,11 +1349,11 @@
    }
  
    Deoptimization::deoptimize_frame(current, caller_frame.id());
    // Return to the now deoptimized frame.
    postcond(caller_is_deopted(current));
- }
+ PROF_END
  
  #endif // DEOPTIMIZE_WHEN_PATCHING
  
  // Entry point for compiled code. We want to patch a nmethod.
  // We don't do a normal VM transition here because we want to

@@ -1434,17 +1440,17 @@
  
    return caller_is_deopted(current);
  }
  
  
- JRT_LEAF(void, Runtime1::trace_block_entry(jint block_id))
+ JRT_LEAF_PROF_NO_THREAD(void, Runtime1, trace_block_entry, Runtime1::trace_block_entry(jint block_id))
    // for now we just print out the block id
    tty->print("%d ", block_id);
  JRT_END
  
  
- JRT_LEAF(int, Runtime1::is_instance_of(oopDesc* mirror, oopDesc* obj))
+ JRT_LEAF_PROF_NO_THREAD(int, Runtime1, is_instance_of, Runtime1::is_instance_of(oopDesc* mirror, oopDesc* obj))
    // had to return int instead of bool, otherwise there may be a mismatch
    // between the C calling convention and the Java one.
    // e.g., on x86, GCC may clear only %al when returning a bool false, but
    // JVM takes the whole %eax as the return value, which may misinterpret
    // the return value as a boolean true.

@@ -1452,11 +1458,11 @@
    assert(mirror != nullptr, "should null-check on mirror before calling");
    Klass* k = java_lang_Class::as_Klass(mirror);
    return (k != nullptr && obj != nullptr && obj->is_a(k)) ? 1 : 0;
  JRT_END
  
- JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current))
+ JRT_ENTRY_PROF(void, Runtime1, predicate_failed_trap, Runtime1::predicate_failed_trap(JavaThread* current))
    ResourceMark rm;
  
    RegisterMap reg_map(current,
                        RegisterMap::UpdateMap::skip,
                        RegisterMap::ProcessFrames::include,

@@ -1512,43 +1518,99 @@
      }
    }
    Exceptions::debug_check_abort(ex->klass()->external_name(), message);
  JRT_END
  
+ #define DO_COUNTERS(macro) \
+   macro(Runtime1, new_instance) \
+   macro(Runtime1, new_type_array) \
+   macro(Runtime1, new_object_array) \
+   macro(Runtime1, new_multi_array) \
+   macro(Runtime1, counter_overflow) \
+   macro(Runtime1, exception_handler_for_pc_helper) \
+   macro(Runtime1, monitorenter) \
+   macro(Runtime1, monitorexit) \
+   macro(Runtime1, deoptimize) \
+   macro(Runtime1, is_instance_of) \
+   macro(Runtime1, predicate_failed_trap) \
+   macro(Runtime1, patch_code)
+ 
+ #define INIT_COUNTER(sub, name) \
+   NEWPERFTICKCOUNTERS(_perf_##sub##_##name##_timer, SUN_CI, #sub "::" #name); \
+   NEWPERFEVENTCOUNTER(_perf_##sub##_##name##_count, SUN_CI, #sub "::" #name "_count");
+ 
+ void Runtime1::init_counters() {
+   assert(CompilerConfig::is_c1_enabled(), "");
+ 
+   if (UsePerfData) {
+     EXCEPTION_MARK;
+ 
+     DO_COUNTERS(INIT_COUNTER)
+ 
+     if (HAS_PENDING_EXCEPTION) {
+       vm_exit_during_initialization("Runtime1::init_counters() failed unexpectedly");
+     }
+   }
+ }
+ #undef INIT_COUNTER
+ 
+ #define PRINT_COUNTER(sub, name) { \
+   if (_perf_##sub##_##name##_count != nullptr) {  \
+     jlong count = _perf_##sub##_##name##_count->get_value(); \
+     if (count > 0) { \
+       st->print_cr("  %-30s = %4ldms (elapsed) %4ldms (thread) (%5ld events)", #sub "::" #name, \
+                    _perf_##sub##_##name##_timer->elapsed_counter_value_ms(), \
+                    _perf_##sub##_##name##_timer->thread_counter_value_ms(), \
+                    count); \
+     }}}
+ 
+ 
+ void Runtime1::print_counters_on(outputStream* st) {
+   if (UsePerfData && ProfileRuntimeCalls && CompilerConfig::is_c1_enabled()) {
+     DO_COUNTERS(PRINT_COUNTER)
+   } else {
+     st->print_cr("  Runtime1: no info (%s is disabled)",
+                  (!CompilerConfig::is_c1_enabled() ? "C1" : (UsePerfData ? "ProfileRuntimeCalls" : "UsePerfData")));
+   }
+ }
+ 
+ #undef PRINT_COUNTER
+ #undef DO_COUNTERS
+ 
  #ifndef PRODUCT
- void Runtime1::print_statistics() {
-   tty->print_cr("C1 Runtime statistics:");
-   tty->print_cr(" _resolve_invoke_virtual_cnt:     %u", SharedRuntime::_resolve_virtual_ctr);
-   tty->print_cr(" _resolve_invoke_opt_virtual_cnt: %u", SharedRuntime::_resolve_opt_virtual_ctr);
-   tty->print_cr(" _resolve_invoke_static_cnt:      %u", SharedRuntime::_resolve_static_ctr);
-   tty->print_cr(" _handle_wrong_method_cnt:        %u", SharedRuntime::_wrong_method_ctr);
-   tty->print_cr(" _ic_miss_cnt:                    %u", SharedRuntime::_ic_miss_ctr);
-   tty->print_cr(" _generic_arraycopystub_cnt:      %u", _generic_arraycopystub_cnt);
-   tty->print_cr(" _byte_arraycopy_cnt:             %u", _byte_arraycopy_stub_cnt);
-   tty->print_cr(" _short_arraycopy_cnt:            %u", _short_arraycopy_stub_cnt);
-   tty->print_cr(" _int_arraycopy_cnt:              %u", _int_arraycopy_stub_cnt);
-   tty->print_cr(" _long_arraycopy_cnt:             %u", _long_arraycopy_stub_cnt);
-   tty->print_cr(" _oop_arraycopy_cnt:              %u", _oop_arraycopy_stub_cnt);
-   tty->print_cr(" _arraycopy_slowcase_cnt:         %u", _arraycopy_slowcase_cnt);
-   tty->print_cr(" _arraycopy_checkcast_cnt:        %u", _arraycopy_checkcast_cnt);
-   tty->print_cr(" _arraycopy_checkcast_attempt_cnt:%u", _arraycopy_checkcast_attempt_cnt);
- 
-   tty->print_cr(" _new_type_array_slowcase_cnt:    %u", _new_type_array_slowcase_cnt);
-   tty->print_cr(" _new_object_array_slowcase_cnt:  %u", _new_object_array_slowcase_cnt);
-   tty->print_cr(" _new_instance_slowcase_cnt:      %u", _new_instance_slowcase_cnt);
-   tty->print_cr(" _new_multi_array_slowcase_cnt:   %u", _new_multi_array_slowcase_cnt);
-   tty->print_cr(" _monitorenter_slowcase_cnt:      %u", _monitorenter_slowcase_cnt);
-   tty->print_cr(" _monitorexit_slowcase_cnt:       %u", _monitorexit_slowcase_cnt);
-   tty->print_cr(" _patch_code_slowcase_cnt:        %u", _patch_code_slowcase_cnt);
- 
-   tty->print_cr(" _throw_range_check_exception_count:            %u:", _throw_range_check_exception_count);
-   tty->print_cr(" _throw_index_exception_count:                  %u:", _throw_index_exception_count);
-   tty->print_cr(" _throw_div0_exception_count:                   %u:", _throw_div0_exception_count);
-   tty->print_cr(" _throw_null_pointer_exception_count:           %u:", _throw_null_pointer_exception_count);
-   tty->print_cr(" _throw_class_cast_exception_count:             %u:", _throw_class_cast_exception_count);
-   tty->print_cr(" _throw_incompatible_class_change_error_count:  %u:", _throw_incompatible_class_change_error_count);
-   tty->print_cr(" _throw_count:                                  %u:", _throw_count);
- 
-   SharedRuntime::print_ic_miss_histogram();
-   tty->cr();
+ void Runtime1::print_statistics_on(outputStream* st) {
+   st->print_cr("C1 Runtime statistics:");
+   st->print_cr(" _resolve_invoke_virtual_cnt:     %u", SharedRuntime::_resolve_virtual_ctr);
+   st->print_cr(" _resolve_invoke_opt_virtual_cnt: %u", SharedRuntime::_resolve_opt_virtual_ctr);
+   st->print_cr(" _resolve_invoke_static_cnt:      %u", SharedRuntime::_resolve_static_ctr);
+   st->print_cr(" _handle_wrong_method_cnt:        %u", SharedRuntime::_wrong_method_ctr);
+   st->print_cr(" _ic_miss_cnt:                    %u", SharedRuntime::_ic_miss_ctr);
+   st->print_cr(" _generic_arraycopystub_cnt:      %u", _generic_arraycopystub_cnt);
+   st->print_cr(" _byte_arraycopy_cnt:             %u", _byte_arraycopy_stub_cnt);
+   st->print_cr(" _short_arraycopy_cnt:            %u", _short_arraycopy_stub_cnt);
+   st->print_cr(" _int_arraycopy_cnt:              %u", _int_arraycopy_stub_cnt);
+   st->print_cr(" _long_arraycopy_cnt:             %u", _long_arraycopy_stub_cnt);
+   st->print_cr(" _oop_arraycopy_cnt:              %u", _oop_arraycopy_stub_cnt);
+   st->print_cr(" _arraycopy_slowcase_cnt:         %u", _arraycopy_slowcase_cnt);
+   st->print_cr(" _arraycopy_checkcast_cnt:        %u", _arraycopy_checkcast_cnt);
+   st->print_cr(" _arraycopy_checkcast_attempt_cnt:%u", _arraycopy_checkcast_attempt_cnt);
+ 
+   st->print_cr(" _new_type_array_slowcase_cnt:    %u", _new_type_array_slowcase_cnt);
+   st->print_cr(" _new_object_array_slowcase_cnt:  %u", _new_object_array_slowcase_cnt);
+   st->print_cr(" _new_instance_slowcase_cnt:      %u", _new_instance_slowcase_cnt);
+   st->print_cr(" _new_multi_array_slowcase_cnt:   %u", _new_multi_array_slowcase_cnt);
+   st->print_cr(" _monitorenter_slowcase_cnt:      %u", _monitorenter_slowcase_cnt);
+   st->print_cr(" _monitorexit_slowcase_cnt:       %u", _monitorexit_slowcase_cnt);
+   st->print_cr(" _patch_code_slowcase_cnt:        %u", _patch_code_slowcase_cnt);
+ 
+   st->print_cr(" _throw_range_check_exception_count:            %u:", _throw_range_check_exception_count);
+   st->print_cr(" _throw_index_exception_count:                  %u:", _throw_index_exception_count);
+   st->print_cr(" _throw_div0_exception_count:                   %u:", _throw_div0_exception_count);
+   st->print_cr(" _throw_null_pointer_exception_count:           %u:", _throw_null_pointer_exception_count);
+   st->print_cr(" _throw_class_cast_exception_count:             %u:", _throw_class_cast_exception_count);
+   st->print_cr(" _throw_incompatible_class_change_error_count:  %u:", _throw_incompatible_class_change_error_count);
+   st->print_cr(" _throw_count:                                  %u:", _throw_count);
+ 
+   SharedRuntime::print_ic_miss_histogram_on(st);
+   st->cr();
  }
  #endif // PRODUCT
< prev index next >