1 /* 2 * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_OOPS_METHODCOUNTERS_HPP 26 #define SHARE_OOPS_METHODCOUNTERS_HPP 27 28 #include "oops/metadata.hpp" 29 #include "compiler/compilerDefinitions.hpp" 30 #include "compiler/compilerOracle.hpp" 31 #include "interpreter/invocationCounter.hpp" 32 #include "utilities/align.hpp" 33 34 class MethodCounters : public Metadata { 35 friend class VMStructs; 36 friend class JVMCIVMStructs; 37 private: 38 InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations 39 InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequency-based optimizations 40 jlong _prev_time; // Previous time the rate was acquired 41 float _rate; // Events (invocation and backedge counter increments) per millisecond 42 int _nmethod_age; 43 int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog 44 int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog 45 int _prev_event_count; // Total number of events saved at previous callback 46 #if COMPILER2_OR_JVMCI 47 u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting 48 #endif 49 #if INCLUDE_JVMTI 50 u2 _number_of_breakpoints; // fullspeed debugging support 51 #endif 52 // NMethod age is a counter for warm methods detection in the code cache sweeper. 53 // The counter is reset by the sweeper and is decremented by some of the compiled 54 // code. The counter values are interpreted as follows: 55 // 1. (HotMethodDetection..INT_MAX] - initial value, no counters inserted 56 // 2. [1..HotMethodDetectionLimit) - the method is warm, the counter is used 57 // to figure out which methods can be flushed. 58 // 3. (INT_MIN..0] - method is hot and will deopt and get 59 // recompiled without the counters 60 u1 _highest_comp_level; // Highest compile level this method has ever seen. 61 u1 _highest_osr_comp_level; // Same for OSR level 62 63 MethodCounters(const methodHandle& mh); 64 public: is_methodCounters() const65 virtual bool is_methodCounters() const { return true; } 66 67 static MethodCounters* allocate_no_exception(const methodHandle& mh); 68 static MethodCounters* allocate_with_exception(const methodHandle& mh, TRAPS); 69 deallocate_contents(ClassLoaderData * loader_data)70 void deallocate_contents(ClassLoaderData* loader_data) {} 71 method_counters_size()72 static int method_counters_size() { 73 return align_up((int)sizeof(MethodCounters), wordSize) / wordSize; 74 } size() const75 virtual int size() const { 76 return method_counters_size(); 77 } type() const78 MetaspaceObj::Type type() const { return MethodCountersType; } 79 void clear_counters(); 80 81 #if COMPILER2_OR_JVMCI interpreter_throwout_increment()82 void interpreter_throwout_increment() { 83 if (_interpreter_throwout_count < 65534) { 84 _interpreter_throwout_count++; 85 } 86 } interpreter_throwout_count() const87 int interpreter_throwout_count() const { 88 return _interpreter_throwout_count; 89 } set_interpreter_throwout_count(int count)90 void set_interpreter_throwout_count(int count) { 91 _interpreter_throwout_count = count; 92 } 93 #else // COMPILER2_OR_JVMCI interpreter_throwout_count() const94 int interpreter_throwout_count() const { 95 return 0; 96 } set_interpreter_throwout_count(int count)97 void set_interpreter_throwout_count(int count) { 98 assert(count == 0, "count must be 0"); 99 } 100 #endif // COMPILER2_OR_JVMCI 101 102 #if INCLUDE_JVMTI number_of_breakpoints() const103 u2 number_of_breakpoints() const { return _number_of_breakpoints; } incr_number_of_breakpoints()104 void incr_number_of_breakpoints() { ++_number_of_breakpoints; } decr_number_of_breakpoints()105 void decr_number_of_breakpoints() { --_number_of_breakpoints; } clear_number_of_breakpoints()106 void clear_number_of_breakpoints() { _number_of_breakpoints = 0; } 107 #endif 108 prev_event_count() const109 int prev_event_count() const { return _prev_event_count; } set_prev_event_count(int count)110 void set_prev_event_count(int count) { _prev_event_count = count; } prev_time() const111 jlong prev_time() const { return _prev_time; } set_prev_time(jlong time)112 void set_prev_time(jlong time) { _prev_time = time; } rate() const113 float rate() const { return _rate; } set_rate(float rate)114 void set_rate(float rate) { _rate = rate; } 115 highest_comp_level() const116 int highest_comp_level() const { return _highest_comp_level; } set_highest_comp_level(int level)117 void set_highest_comp_level(int level) { _highest_comp_level = level; } highest_osr_comp_level() const118 int highest_osr_comp_level() const { return _highest_osr_comp_level; } set_highest_osr_comp_level(int level)119 void set_highest_osr_comp_level(int level) { _highest_osr_comp_level = level; } 120 121 // invocation counter invocation_counter()122 InvocationCounter* invocation_counter() { return &_invocation_counter; } backedge_counter()123 InvocationCounter* backedge_counter() { return &_backedge_counter; } 124 nmethod_age()125 int nmethod_age() { 126 return _nmethod_age; 127 } set_nmethod_age(int age)128 void set_nmethod_age(int age) { 129 _nmethod_age = age; 130 } reset_nmethod_age()131 void reset_nmethod_age() { 132 set_nmethod_age(HotMethodDetectionLimit); 133 } 134 is_nmethod_hot(int age)135 static bool is_nmethod_hot(int age) { return age <= 0; } is_nmethod_warm(int age)136 static bool is_nmethod_warm(int age) { return age < HotMethodDetectionLimit; } is_nmethod_age_unset(int age)137 static bool is_nmethod_age_unset(int age) { return age > HotMethodDetectionLimit; } 138 nmethod_age_offset()139 static ByteSize nmethod_age_offset() { 140 return byte_offset_of(MethodCounters, _nmethod_age); 141 } 142 invocation_counter_offset()143 static ByteSize invocation_counter_offset() { 144 return byte_offset_of(MethodCounters, _invocation_counter); 145 } 146 backedge_counter_offset()147 static ByteSize backedge_counter_offset() { 148 return byte_offset_of(MethodCounters, _backedge_counter); 149 } 150 invoke_mask_offset()151 static ByteSize invoke_mask_offset() { 152 return byte_offset_of(MethodCounters, _invoke_mask); 153 } 154 backedge_mask_offset()155 static ByteSize backedge_mask_offset() { 156 return byte_offset_of(MethodCounters, _backedge_mask); 157 } 158 internal_name() const159 virtual const char* internal_name() const { return "{method counters}"; } 160 virtual void print_value_on(outputStream* st) const; 161 162 }; 163 #endif // SHARE_OOPS_METHODCOUNTERS_HPP 164