|
1 | 1 | /* |
2 | | - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
@@ -72,44 +72,48 @@ int NativeCallStack::frames() const { |
72 | 72 | } |
73 | 73 |
|
74 | 74 | // Decode and print this call path |
75 | | -void NativeCallStack::print_on(outputStream* out) const { |
76 | | - DEBUG_ONLY(assert_not_fake();) |
77 | | - address pc; |
| 75 | + |
| 76 | +void NativeCallStack::print_frame(outputStream* out, address pc) const { |
78 | 77 | char buf[1024]; |
79 | 78 | int offset; |
80 | | - if (is_empty()) { |
81 | | - out->print("[BOOTSTRAP]"); |
82 | | - } else { |
83 | | - for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) { |
84 | | - pc = get_frame(frame); |
85 | | - if (pc == nullptr) break; |
86 | | - out->print("[" PTR_FORMAT "]", p2i(pc)); |
87 | | - // Print function and library; shorten library name to just its last component |
88 | | - // for brevity, and omit it completely for libjvm.so |
89 | | - bool function_printed = false; |
90 | | - if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { |
91 | | - out->print("%s+0x%x", buf, offset); |
92 | | - function_printed = true; |
93 | | - } |
94 | | - if ((!function_printed || !os::address_is_in_vm(pc)) && |
95 | | - os::dll_address_to_library_name(pc, buf, sizeof(buf), &offset)) { |
96 | | - const char* libname = strrchr(buf, os::file_separator()[0]); |
97 | | - if (libname != nullptr) { |
98 | | - libname++; |
99 | | - } else { |
100 | | - libname = buf; |
101 | | - } |
102 | | - out->print(" in %s", libname); |
103 | | - if (!function_printed) { |
104 | | - out->print("+0x%x", offset); |
105 | | - } |
| 79 | + int line; |
| 80 | + const bool pc_in_VM = os::address_is_in_vm(pc); |
| 81 | + out->print("[" PTR_FORMAT "]", p2i(pc)); |
| 82 | + // Print function and library; shorten library name to just its last component |
| 83 | + // for brevity, and omit it completely for libjvm.so |
| 84 | + bool function_printed = false; |
| 85 | + if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { |
| 86 | + out->print("%s+0x%x", buf, offset); |
| 87 | + function_printed = true; |
| 88 | + if (Decoder::get_source_info(pc, buf, sizeof(buf), &line, false)) { |
| 89 | + // For intra-vm functions, we omit the full path |
| 90 | + const char* s = buf; |
| 91 | + if (pc_in_VM) { |
| 92 | + s = strrchr(s, os::file_separator()[0]); |
| 93 | + s = (s != nullptr) ? s + 1 : buf; |
106 | 94 | } |
107 | | - |
108 | | - // Note: we deliberately omit printing source information here. NativeCallStack::print_on() |
109 | | - // can be called thousands of times as part of NMT detail reporting, and source printing |
110 | | - // can slow down reporting by a factor of 5 or more depending on platform (see JDK-8296931). |
111 | | - |
112 | | - out->cr(); |
| 95 | + out->print(" (%s:%d)", s, line); |
| 96 | + } |
| 97 | + } |
| 98 | + if ((!function_printed || !pc_in_VM) && |
| 99 | + os::dll_address_to_library_name(pc, buf, sizeof(buf), &offset)) { |
| 100 | + const char* libname = strrchr(buf, os::file_separator()[0]); |
| 101 | + if (libname != nullptr) { |
| 102 | + libname++; |
| 103 | + } else { |
| 104 | + libname = buf; |
| 105 | + } |
| 106 | + out->print(" in %s", libname); |
| 107 | + if (!function_printed) { |
| 108 | + out->print("+0x%x", offset); |
113 | 109 | } |
114 | 110 | } |
115 | 111 | } |
| 112 | + |
| 113 | +void NativeCallStack::print_on(outputStream* out) const { |
| 114 | + DEBUG_ONLY(assert_not_fake();) |
| 115 | + for (int i = 0; i < NMT_TrackingStackDepth && _stack[i] != nullptr; i++) { |
| 116 | + print_frame(out, _stack[i]); |
| 117 | + } |
| 118 | + out->cr(); |
| 119 | +} |
0 commit comments