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