65 static inline void record_arena_free(MEMFLAGS flag) { }
66 static inline void record_arena_size_change(int diff, MEMFLAGS flag) { }
67 static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
68 MEMFLAGS flag = mtNone) { }
69 static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
70 const NativeCallStack& stack, MEMFLAGS flag = mtNone) { }
71 static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { }
72 static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { }
73 static inline void record_thread_stack(void* addr, size_t size) { }
74 static inline void release_thread_stack(void* addr, size_t size) { }
75
76 static void final_report(outputStream*) { }
77 static void error_report(outputStream*) { }
78 };
79
80 #else
81
82 #include "runtime/mutexLocker.hpp"
83 #include "runtime/threadCritical.hpp"
84 #include "services/mallocTracker.hpp"
85 #include "services/virtualMemoryTracker.hpp"
86
87 extern volatile bool NMT_stack_walkable;
88
89 #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
90 NativeCallStack(0, true) : NativeCallStack::empty_stack())
91 #define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
92 NativeCallStack(1, true) : NativeCallStack::empty_stack())
93
94 class MemBaseline;
95
96 // Tracker is used for guarding 'release' semantics of virtual memory operation, to avoid
97 // the other thread obtains and records the same region that is just 'released' by current
98 // thread but before it can record the operation.
99 class Tracker : public StackObj {
100 public:
101 enum TrackerType {
102 uncommit,
103 release
104 };
224
225 static inline void record_virtual_memory_commit(void* addr, size_t size,
226 const NativeCallStack& stack) {
227 if (tracking_level() < NMT_summary) return;
228 if (addr != NULL) {
229 ThreadCritical tc;
230 if (tracking_level() < NMT_summary) return;
231 VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
232 }
233 }
234
235 static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) {
236 if (tracking_level() < NMT_summary) return;
237 if (addr != NULL) {
238 ThreadCritical tc;
239 if (tracking_level() < NMT_summary) return;
240 VirtualMemoryTracker::set_reserved_region_type((address)addr, flag);
241 }
242 }
243
244 #ifdef _AIX
245 // See JDK-8202772 - temporarily disable thread stack tracking on AIX.
246 static inline void record_thread_stack(void* addr, size_t size) {}
247 static inline void release_thread_stack(void* addr, size_t size) {}
248 #else
249 static inline void record_thread_stack(void* addr, size_t size) {
250 if (tracking_level() < NMT_summary) return;
251 if (addr != NULL) {
252 // uses thread stack malloc slot for book keeping number of threads
253 MallocMemorySummary::record_malloc(0, mtThreadStack);
254 record_virtual_memory_reserve(addr, size, CALLER_PC, mtThreadStack);
255 }
256 }
257
258 static inline void release_thread_stack(void* addr, size_t size) {
259 if (tracking_level() < NMT_summary) return;
260 if (addr != NULL) {
261 // uses thread stack malloc slot for book keeping number of threads
262 MallocMemorySummary::record_free(0, mtThreadStack);
263 ThreadCritical tc;
264 if (tracking_level() < NMT_summary) return;
265 VirtualMemoryTracker::remove_released_region((address)addr, size);
266 }
267 }
268 #endif
269
270 // Query lock is used to synchronize the access to tracking data.
271 // So far, it is only used by JCmd query, but it may be used by
272 // other tools.
273 static inline Mutex* query_lock() {
274 assert(NMTQuery_lock != NULL, "not initialized!");
275 return NMTQuery_lock;
276 }
277
278 // Make a final report or report for hs_err file.
279 static void error_report(outputStream* output) {
280 if (tracking_level() >= NMT_summary) {
281 report(true, output); // just print summary for error case.
282 }
283 }
284
285 static void final_report(outputStream* output) {
286 NMT_TrackingLevel level = tracking_level();
287 if (level >= NMT_summary) {
288 report(level == NMT_summary, output);
|
65 static inline void record_arena_free(MEMFLAGS flag) { }
66 static inline void record_arena_size_change(int diff, MEMFLAGS flag) { }
67 static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
68 MEMFLAGS flag = mtNone) { }
69 static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
70 const NativeCallStack& stack, MEMFLAGS flag = mtNone) { }
71 static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { }
72 static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { }
73 static inline void record_thread_stack(void* addr, size_t size) { }
74 static inline void release_thread_stack(void* addr, size_t size) { }
75
76 static void final_report(outputStream*) { }
77 static void error_report(outputStream*) { }
78 };
79
80 #else
81
82 #include "runtime/mutexLocker.hpp"
83 #include "runtime/threadCritical.hpp"
84 #include "services/mallocTracker.hpp"
85 #include "services/threadStackTracker.hpp"
86 #include "services/virtualMemoryTracker.hpp"
87
88 extern volatile bool NMT_stack_walkable;
89
90 #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
91 NativeCallStack(0, true) : NativeCallStack::empty_stack())
92 #define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
93 NativeCallStack(1, true) : NativeCallStack::empty_stack())
94
95 class MemBaseline;
96
97 // Tracker is used for guarding 'release' semantics of virtual memory operation, to avoid
98 // the other thread obtains and records the same region that is just 'released' by current
99 // thread but before it can record the operation.
100 class Tracker : public StackObj {
101 public:
102 enum TrackerType {
103 uncommit,
104 release
105 };
225
226 static inline void record_virtual_memory_commit(void* addr, size_t size,
227 const NativeCallStack& stack) {
228 if (tracking_level() < NMT_summary) return;
229 if (addr != NULL) {
230 ThreadCritical tc;
231 if (tracking_level() < NMT_summary) return;
232 VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
233 }
234 }
235
236 static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) {
237 if (tracking_level() < NMT_summary) return;
238 if (addr != NULL) {
239 ThreadCritical tc;
240 if (tracking_level() < NMT_summary) return;
241 VirtualMemoryTracker::set_reserved_region_type((address)addr, flag);
242 }
243 }
244
245 static void record_thread_stack(void* addr, size_t size) {
246 if (tracking_level() < NMT_summary) return;
247 if (addr != NULL) {
248 ThreadStackTracker::new_thread_stack((address)addr, size, CALLER_PC);
249 }
250 }
251
252 static inline void release_thread_stack(void* addr, size_t size) {
253 if (tracking_level() < NMT_summary) return;
254 if (addr != NULL) {
255 ThreadStackTracker::delete_thread_stack((address)addr, size);
256 }
257 }
258
259 // Query lock is used to synchronize the access to tracking data.
260 // So far, it is only used by JCmd query, but it may be used by
261 // other tools.
262 static inline Mutex* query_lock() {
263 assert(NMTQuery_lock != NULL, "not initialized!");
264 return NMTQuery_lock;
265 }
266
267 // Make a final report or report for hs_err file.
268 static void error_report(outputStream* output) {
269 if (tracking_level() >= NMT_summary) {
270 report(true, output); // just print summary for error case.
271 }
272 }
273
274 static void final_report(outputStream* output) {
275 NMT_TrackingLevel level = tracking_level();
276 if (level >= NMT_summary) {
277 report(level == NMT_summary, output);
|