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 #include "classfile/classPrinter.hpp"
26 #include "classfile/javaClasses.inline.hpp"
27 #include "interpreter/bytecodeHistogram.hpp"
28 #include "interpreter/bytecodes.hpp"
29 #include "interpreter/bytecodeStream.hpp"
30 #include "interpreter/bytecodeTracer.hpp"
31 #include "interpreter/interpreter.hpp"
32 #include "memory/resourceArea.hpp"
33 #include "oops/constantPool.inline.hpp"
34 #include "oops/method.hpp"
35 #include "oops/methodData.hpp"
36 #include "runtime/atomic.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "runtime/osThread.hpp"
40 #include "utilities/align.hpp"
41
42 // Prints the current bytecode and its attributes using bytecode-specific information.
43
44 class BytecodePrinter {
154 ResourceMark rm;
155 Bytecodes::Code code = Bytecodes::code_at(method(), bcp);
156 // Set is_wide
157 _is_wide = (code == Bytecodes::_wide);
158 if (is_wide()) {
159 code = Bytecodes::code_at(method(), bcp+1);
160 }
161 _code = code;
162 int bci = (int)(bcp - method->code_base());
163 // Print bytecode index and name
164 if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_BYTECODE_ADDR)) {
165 st->print(INTPTR_FORMAT " ", p2i(bcp));
166 }
167 if (is_wide()) {
168 st->print("%4d %s_w", bci, Bytecodes::name(code));
169 } else {
170 st->print("%4d %s", bci, Bytecodes::name(code));
171 }
172 _next_pc = is_wide() ? bcp+2 : bcp+1;
173 print_attributes(bci, st);
174 bytecode_epilog(bci, st);
175 }
176 };
177
178 #ifndef PRODUCT
179 // We need a global instance to keep track of the method being printed so we can report that
180 // the method has changed. If this method is redefined and removed, that's ok because the method passed
181 // in won't match, and this will print the method passed in again. Racing threads changing this global
182 // will result in reprinting the method passed in again.
183 static Method* _method_currently_being_printed = nullptr;
184
185 void BytecodeTracer::trace_interpreter(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
186 if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) {
187 BytecodePrinter printer(Atomic::load_acquire(&_method_currently_being_printed));
188 printer.trace(method, bcp, tos, tos2, st);
189 // Save method currently being printed to detect when method printing changes.
190 Atomic::release_store(&_method_currently_being_printed, method());
191 }
192 }
193 #endif
194
282
283 int bsm = constants->bootstrap_method_ref_index_at(cp_index);
284 st->print(" bsm=%d", bsm);
285
286 Symbol* name = constants->uncached_name_ref_at(cp_index);
287 Symbol* signature = constants->uncached_signature_ref_at(cp_index);
288 const char* sep = tag.is_dynamic_constant() ? ":" : "";
289 st->print_cr(" %d <%s%s%s>", cp_index, name->as_C_string(), sep, signature->as_C_string());
290 }
291
292 void BytecodePrinter::print_invokedynamic(int indy_index, int cp_index, outputStream* st) {
293 print_dynamic(cp_index, st);
294
295 if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_DYNAMIC)) {
296 print_bsm(cp_index, st);
297
298 if (is_linked()) {
299 ResolvedIndyEntry* indy_entry = constants()->resolved_indy_entry_at(indy_index);
300 st->print(" ResolvedIndyEntry: ");
301 indy_entry->print_on(st);
302 }
303 }
304 }
305
306 // cp_index: must be the cp_index of a JVM_CONSTANT_{Dynamic, DynamicInError, InvokeDynamic}
307 void BytecodePrinter::print_bsm(int cp_index, outputStream* st) {
308 assert(constants()->tag_at(cp_index).has_bootstrap(), "must be");
309 int bsm = constants()->bootstrap_method_ref_index_at(cp_index);
310 const char* ref_kind = "";
311 switch (constants()->method_handle_ref_kind_at(bsm)) {
312 case JVM_REF_getField : ref_kind = "REF_getField"; break;
313 case JVM_REF_getStatic : ref_kind = "REF_getStatic"; break;
314 case JVM_REF_putField : ref_kind = "REF_putField"; break;
315 case JVM_REF_putStatic : ref_kind = "REF_putStatic"; break;
316 case JVM_REF_invokeVirtual : ref_kind = "REF_invokeVirtual"; break;
317 case JVM_REF_invokeStatic : ref_kind = "REF_invokeStatic"; break;
318 case JVM_REF_invokeSpecial : ref_kind = "REF_invokeSpecial"; break;
319 case JVM_REF_newInvokeSpecial : ref_kind = "REF_newInvokeSpecial"; break;
320 case JVM_REF_invokeInterface : ref_kind = "REF_invokeInterface"; break;
321 default : ShouldNotReachHere();
|
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 #include "cds/heapShared.hpp"
26 #include "classfile/classPrinter.hpp"
27 #include "classfile/javaClasses.inline.hpp"
28 #include "interpreter/bytecodeHistogram.hpp"
29 #include "interpreter/bytecodes.hpp"
30 #include "interpreter/bytecodeStream.hpp"
31 #include "interpreter/bytecodeTracer.hpp"
32 #include "interpreter/interpreter.hpp"
33 #include "memory/resourceArea.hpp"
34 #include "oops/constantPool.inline.hpp"
35 #include "oops/method.hpp"
36 #include "oops/methodData.hpp"
37 #include "runtime/atomic.hpp"
38 #include "runtime/handles.inline.hpp"
39 #include "runtime/mutexLocker.hpp"
40 #include "runtime/osThread.hpp"
41 #include "utilities/align.hpp"
42
43 // Prints the current bytecode and its attributes using bytecode-specific information.
44
45 class BytecodePrinter {
155 ResourceMark rm;
156 Bytecodes::Code code = Bytecodes::code_at(method(), bcp);
157 // Set is_wide
158 _is_wide = (code == Bytecodes::_wide);
159 if (is_wide()) {
160 code = Bytecodes::code_at(method(), bcp+1);
161 }
162 _code = code;
163 int bci = (int)(bcp - method->code_base());
164 // Print bytecode index and name
165 if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_BYTECODE_ADDR)) {
166 st->print(INTPTR_FORMAT " ", p2i(bcp));
167 }
168 if (is_wide()) {
169 st->print("%4d %s_w", bci, Bytecodes::name(code));
170 } else {
171 st->print("%4d %s", bci, Bytecodes::name(code));
172 }
173 _next_pc = is_wide() ? bcp+2 : bcp+1;
174 print_attributes(bci, st);
175 if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_PROFILE)) {
176 bytecode_epilog(bci, st);
177 }
178 }
179 };
180
181 #ifndef PRODUCT
182 // We need a global instance to keep track of the method being printed so we can report that
183 // the method has changed. If this method is redefined and removed, that's ok because the method passed
184 // in won't match, and this will print the method passed in again. Racing threads changing this global
185 // will result in reprinting the method passed in again.
186 static Method* _method_currently_being_printed = nullptr;
187
188 void BytecodeTracer::trace_interpreter(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
189 if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) {
190 BytecodePrinter printer(Atomic::load_acquire(&_method_currently_being_printed));
191 printer.trace(method, bcp, tos, tos2, st);
192 // Save method currently being printed to detect when method printing changes.
193 Atomic::release_store(&_method_currently_being_printed, method());
194 }
195 }
196 #endif
197
285
286 int bsm = constants->bootstrap_method_ref_index_at(cp_index);
287 st->print(" bsm=%d", bsm);
288
289 Symbol* name = constants->uncached_name_ref_at(cp_index);
290 Symbol* signature = constants->uncached_signature_ref_at(cp_index);
291 const char* sep = tag.is_dynamic_constant() ? ":" : "";
292 st->print_cr(" %d <%s%s%s>", cp_index, name->as_C_string(), sep, signature->as_C_string());
293 }
294
295 void BytecodePrinter::print_invokedynamic(int indy_index, int cp_index, outputStream* st) {
296 print_dynamic(cp_index, st);
297
298 if (ClassPrinter::has_mode(_flags, ClassPrinter::PRINT_DYNAMIC)) {
299 print_bsm(cp_index, st);
300
301 if (is_linked()) {
302 ResolvedIndyEntry* indy_entry = constants()->resolved_indy_entry_at(indy_index);
303 st->print(" ResolvedIndyEntry: ");
304 indy_entry->print_on(st);
305 if (indy_entry->has_appendix()) {
306 oop apx = constants()->resolved_reference_from_indy(indy_index);
307 st->print_cr(" - appendix = " INTPTR_FORMAT, p2i(apx));
308 }
309 }
310 }
311 }
312
313 // cp_index: must be the cp_index of a JVM_CONSTANT_{Dynamic, DynamicInError, InvokeDynamic}
314 void BytecodePrinter::print_bsm(int cp_index, outputStream* st) {
315 assert(constants()->tag_at(cp_index).has_bootstrap(), "must be");
316 int bsm = constants()->bootstrap_method_ref_index_at(cp_index);
317 const char* ref_kind = "";
318 switch (constants()->method_handle_ref_kind_at(bsm)) {
319 case JVM_REF_getField : ref_kind = "REF_getField"; break;
320 case JVM_REF_getStatic : ref_kind = "REF_getStatic"; break;
321 case JVM_REF_putField : ref_kind = "REF_putField"; break;
322 case JVM_REF_putStatic : ref_kind = "REF_putStatic"; break;
323 case JVM_REF_invokeVirtual : ref_kind = "REF_invokeVirtual"; break;
324 case JVM_REF_invokeStatic : ref_kind = "REF_invokeStatic"; break;
325 case JVM_REF_invokeSpecial : ref_kind = "REF_invokeSpecial"; break;
326 case JVM_REF_newInvokeSpecial : ref_kind = "REF_newInvokeSpecial"; break;
327 case JVM_REF_invokeInterface : ref_kind = "REF_invokeInterface"; break;
328 default : ShouldNotReachHere();
|