1 /*
2 * Copyright (c) 2018, 2025, 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_METHOD_INLINE_HPP
26 #define SHARE_OOPS_METHOD_INLINE_HPP
27
28 #include "oops/method.hpp"
29
30 #include "classfile/vmIntrinsics.hpp"
31 #include "code/nmethod.inline.hpp"
32 #include "oops/methodCounters.hpp"
33 #include "oops/methodData.inline.hpp"
34 #include "runtime/atomicAccess.hpp"
35
36 inline address Method::from_compiled_entry() const {
37 return AtomicAccess::load_acquire(&_from_compiled_entry);
38 }
39
40 inline address Method::from_compiled_inline_ro_entry() const {
41 return AtomicAccess::load_acquire(&_from_compiled_inline_ro_entry);
42 }
43
44 inline address Method::from_compiled_inline_entry() const {
45 return AtomicAccess::load_acquire(&_from_compiled_inline_entry);
46 }
47
48 inline address Method::from_interpreted_entry() const {
49 return AtomicAccess::load_acquire(&_from_interpreted_entry);
50 }
51
52 inline nmethod* Method::code() const {
53 assert( check_code(), "" );
54 return AtomicAccess::load_acquire(&_code);
55 }
56
57 // Write (bci, line number) pair to stream
58 inline void CompressedLineNumberWriteStream::write_pair_regular(int bci_delta, int line_delta) {
59 // bci and line number does not compress into single byte.
60 // Write out escape character and use regular compression for bci and line number.
61 write_byte((jubyte)0xFF);
62 write_signed_int(bci_delta);
63 write_signed_int(line_delta);
64 }
65
66 inline void CompressedLineNumberWriteStream::write_pair_inline(int bci, int line) {
67 int bci_delta = bci - _bci;
68 int line_delta = line - _line;
69 _bci = bci;
70 _line = line;
71 // Skip (0,0) deltas - they do not add information and conflict with terminator.
72 if (bci_delta == 0 && line_delta == 0) return;
73 // Check if bci is 5-bit and line number 3-bit unsigned.
74 if (((bci_delta & ~0x1F) == 0) && ((line_delta & ~0x7) == 0)) {
75 // Compress into single byte.
76 jubyte value = (jubyte)((bci_delta << 3) | line_delta);
77 // Check that value doesn't match escape character.
78 if (value != 0xFF) {
79 write_byte(value);
80 return;
81 }
82 }
83 write_pair_regular(bci_delta, line_delta);
84 }
85
86 inline void CompressedLineNumberWriteStream::write_pair(int bci, int line) {
87 write_pair_inline(bci, line);
88 }
89
90 inline bool Method::has_compiled_code() const { return code() != nullptr; }
91
92 inline bool Method::is_empty_method() const {
93 return code_size() == 1
94 && *code_base() == Bytecodes::_return;
95 }
96
97 inline bool Method::is_continuation_enter_intrinsic() const {
98 return intrinsic_id() == vmIntrinsics::_Continuation_enterSpecial;
99 }
100
101 inline bool Method::is_continuation_yield_intrinsic() const {
102 return intrinsic_id() == vmIntrinsics::_Continuation_doYield;
103 }
104
105 inline bool Method::is_continuation_native_intrinsic() const {
106 return intrinsic_id() == vmIntrinsics::_Continuation_enterSpecial ||
107 intrinsic_id() == vmIntrinsics::_Continuation_doYield;
108 }
109
110 inline bool Method::is_special_native_intrinsic() const {
111 return is_method_handle_intrinsic() || is_continuation_native_intrinsic();
112 }
113
114 #if INCLUDE_JVMTI
115 inline u2 Method::number_of_breakpoints() const {
116 MethodCounters* mcs = method_counters();
117 if (mcs == nullptr) {
118 return 0;
119 } else {
120 return mcs->number_of_breakpoints();
121 }
122 }
123
124 inline void Method::incr_number_of_breakpoints(Thread* current) {
125 MethodCounters* mcs = get_method_counters(current);
126 if (mcs != nullptr) {
127 mcs->incr_number_of_breakpoints();
128 }
129 }
130
131 inline void Method::decr_number_of_breakpoints(Thread* current) {
132 MethodCounters* mcs = get_method_counters(current);
133 if (mcs != nullptr) {
134 mcs->decr_number_of_breakpoints();
135 }
136 }
137
138 // Initialization only
139 inline void Method::clear_number_of_breakpoints() {
140 MethodCounters* mcs = method_counters();
141 if (mcs != nullptr) {
142 mcs->clear_number_of_breakpoints();
143 }
144 }
145 #endif // INCLUDE_JVMTI
146
147 #if COMPILER2_OR_JVMCI
148 inline void Method::interpreter_throwout_increment(Thread* current) {
149 MethodCounters* mcs = get_method_counters(current);
150 if (mcs != nullptr) {
151 mcs->interpreter_throwout_increment();
152 }
153 }
154 #endif
155
156 inline int Method::interpreter_throwout_count() const {
157 MethodCounters* mcs = method_counters();
158 if (mcs == nullptr) {
159 return 0;
160 } else {
161 return mcs->interpreter_throwout_count();
162 }
163 }
164
165 inline int Method::prev_event_count() const {
166 MethodCounters* mcs = method_counters();
167 return mcs == nullptr ? 0 : mcs->prev_event_count();
168 }
169
170 inline void Method::set_prev_event_count(int count) {
171 MethodCounters* mcs = method_counters();
172 if (mcs != nullptr) {
173 mcs->set_prev_event_count(count);
174 }
175 }
176
177 inline jlong Method::prev_time() const {
178 MethodCounters* mcs = method_counters();
179 return mcs == nullptr ? 0 : mcs->prev_time();
180 }
181
182 inline void Method::set_prev_time(jlong time) {
183 MethodCounters* mcs = method_counters();
184 if (mcs != nullptr) {
185 mcs->set_prev_time(time);
186 }
187 }
188
189 inline float Method::rate() const {
190 MethodCounters* mcs = method_counters();
191 return mcs == nullptr ? 0 : mcs->rate();
192 }
193
194 inline void Method::set_rate(float rate) {
195 MethodCounters* mcs = method_counters();
196 if (mcs != nullptr) {
197 mcs->set_rate(rate);
198 }
199 }
200
201 inline int Method::invocation_count() const {
202 MethodCounters* mcs = method_counters();
203 MethodData* mdo = method_data();
204 if (((mcs != nullptr) ? mcs->invocation_counter()->carry() : false) ||
205 ((mdo != nullptr) ? mdo->invocation_counter()->carry() : false)) {
206 return InvocationCounter::count_limit;
207 } else {
208 return ((mcs != nullptr) ? mcs->invocation_counter()->count() : 0) +
209 ((mdo != nullptr) ? mdo->invocation_counter()->count() : 0);
210 }
211 }
212
213 inline int Method::backedge_count() const {
214 MethodCounters* mcs = method_counters();
215 MethodData* mdo = method_data();
216 if (((mcs != nullptr) ? mcs->backedge_counter()->carry() : false) ||
217 ((mdo != nullptr) ? mdo->backedge_counter()->carry() : false)) {
218 return InvocationCounter::count_limit;
219 } else {
220 return ((mcs != nullptr) ? mcs->backedge_counter()->count() : 0) +
221 ((mdo != nullptr) ? mdo->backedge_counter()->count() : 0);
222 }
223 }
224
225 inline int Method::highest_comp_level() const {
226 const MethodCounters* mcs = method_counters();
227 if (mcs != nullptr) {
228 return mcs->highest_comp_level();
229 } else {
230 return CompLevel_none;
231 }
232 }
233
234 inline int Method::interpreter_invocation_count() const {
235 return invocation_count();
236 }
237
238 #endif // SHARE_OOPS_METHOD_INLINE_HPP