Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/services/memTracker.hpp
41144 views
1
/*
2
* Copyright (c) 2013, 2020, 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_SERVICES_MEMTRACKER_HPP
26
#define SHARE_SERVICES_MEMTRACKER_HPP
27
28
#include "services/nmtCommon.hpp"
29
#include "utilities/nativeCallStack.hpp"
30
31
32
#if !INCLUDE_NMT
33
34
#define CURRENT_PC NativeCallStack::empty_stack()
35
#define CALLER_PC NativeCallStack::empty_stack()
36
37
class Tracker : public StackObj {
38
public:
39
enum TrackerType {
40
uncommit,
41
release
42
};
43
Tracker(enum TrackerType type) : _type(type) { }
44
void record(address addr, size_t size) { }
45
private:
46
enum TrackerType _type;
47
};
48
49
class MemTracker : AllStatic {
50
public:
51
static inline NMT_TrackingLevel tracking_level() { return NMT_off; }
52
static inline void shutdown() { }
53
static inline void init() { }
54
static bool check_launcher_nmt_support(const char* value) { return true; }
55
static bool verify_nmt_option() { return true; }
56
57
static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag,
58
const NativeCallStack& stack, NMT_TrackingLevel level) { return mem_base; }
59
static inline size_t malloc_header_size(NMT_TrackingLevel level) { return 0; }
60
static inline size_t malloc_header_size(void* memblock) { return 0; }
61
static inline void* malloc_base(void* memblock) { return memblock; }
62
static inline void* record_free(void* memblock, NMT_TrackingLevel level) { return memblock; }
63
64
static inline void record_new_arena(MEMFLAGS flag) { }
65
static inline void record_arena_free(MEMFLAGS flag) { }
66
static inline void record_arena_size_change(ssize_t 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_split_reserved(void* addr, size_t size, size_t split) { }
72
static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { }
73
static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { }
74
static inline void record_thread_stack(void* addr, size_t size) { }
75
static inline void release_thread_stack(void* addr, size_t size) { }
76
77
static void final_report(outputStream*) { }
78
static void error_report(outputStream*) { }
79
};
80
81
#else
82
83
#include "runtime/mutexLocker.hpp"
84
#include "runtime/threadCritical.hpp"
85
#include "services/mallocTracker.hpp"
86
#include "services/threadStackTracker.hpp"
87
#include "services/virtualMemoryTracker.hpp"
88
89
#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \
90
NativeCallStack(0) : NativeCallStack::empty_stack())
91
#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail) ? \
92
NativeCallStack(1) : 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
};
105
106
public:
107
Tracker(enum TrackerType type) : _type(type) { }
108
void record(address addr, size_t size);
109
private:
110
enum TrackerType _type;
111
// Virtual memory tracking data structures are protected by ThreadCritical lock.
112
ThreadCritical _tc;
113
};
114
115
class MemTracker : AllStatic {
116
friend class VirtualMemoryTrackerTest;
117
118
public:
119
static inline NMT_TrackingLevel tracking_level() {
120
if (_tracking_level == NMT_unknown) {
121
// No fencing is needed here, since JVM is in single-threaded
122
// mode.
123
_tracking_level = init_tracking_level();
124
_cmdline_tracking_level = _tracking_level;
125
}
126
return _tracking_level;
127
}
128
129
// A late initialization, for the stuff(s) can not be
130
// done in init_tracking_level(), which can NOT malloc
131
// any memory.
132
static void init();
133
134
// Shutdown native memory tracking
135
static void shutdown();
136
137
// Verify native memory tracking command line option.
138
// This check allows JVM to detect if compatible launcher
139
// is used.
140
// If an incompatible launcher is used, NMT may not be
141
// able to start, even it is enabled by command line option.
142
// A warning message should be given if it is encountered.
143
static bool check_launcher_nmt_support(const char* value);
144
145
// This method checks native memory tracking environment
146
// variable value passed by launcher.
147
// Launcher only obligated to pass native memory tracking
148
// option value, but not obligated to validate the value,
149
// and launcher has option to discard native memory tracking
150
// option from the command line once it sets up the environment
151
// variable, so NMT has to catch the bad value here.
152
static bool verify_nmt_option();
153
154
// Transition the tracking level to specified level
155
static bool transition_to(NMT_TrackingLevel level);
156
157
static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag,
158
const NativeCallStack& stack, NMT_TrackingLevel level) {
159
if (level != NMT_off) {
160
return MallocTracker::record_malloc(mem_base, size, flag, stack, level);
161
}
162
return mem_base;
163
}
164
165
static inline size_t malloc_header_size(NMT_TrackingLevel level) {
166
return MallocTracker::malloc_header_size(level);
167
}
168
169
static size_t malloc_header_size(void* memblock) {
170
if (tracking_level() != NMT_off) {
171
return MallocTracker::get_header_size(memblock);
172
}
173
return 0;
174
}
175
176
// To malloc base address, which is the starting address
177
// of malloc tracking header if tracking is enabled.
178
// Otherwise, it returns the same address.
179
static void* malloc_base(void* memblock);
180
181
// Record malloc free and return malloc base address
182
static inline void* record_free(void* memblock, NMT_TrackingLevel level) {
183
// Never turned on
184
if (level == NMT_off || memblock == NULL) {
185
return memblock;
186
}
187
return MallocTracker::record_free(memblock);
188
}
189
190
191
// Record creation of an arena
192
static inline void record_new_arena(MEMFLAGS flag) {
193
if (tracking_level() < NMT_summary) return;
194
MallocTracker::record_new_arena(flag);
195
}
196
197
// Record destruction of an arena
198
static inline void record_arena_free(MEMFLAGS flag) {
199
if (tracking_level() < NMT_summary) return;
200
MallocTracker::record_arena_free(flag);
201
}
202
203
// Record arena size change. Arena size is the size of all arena
204
// chuncks that backing up the arena.
205
static inline void record_arena_size_change(ssize_t diff, MEMFLAGS flag) {
206
if (tracking_level() < NMT_summary) return;
207
MallocTracker::record_arena_size_change(diff, flag);
208
}
209
210
static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
211
MEMFLAGS flag = mtNone) {
212
if (tracking_level() < NMT_summary) return;
213
if (addr != NULL) {
214
ThreadCritical tc;
215
// Recheck to avoid potential racing during NMT shutdown
216
if (tracking_level() < NMT_summary) return;
217
VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag);
218
}
219
}
220
221
static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
222
const NativeCallStack& stack, MEMFLAGS flag = mtNone) {
223
if (tracking_level() < NMT_summary) return;
224
if (addr != NULL) {
225
ThreadCritical tc;
226
if (tracking_level() < NMT_summary) return;
227
VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag);
228
VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
229
}
230
}
231
232
static inline void record_virtual_memory_commit(void* addr, size_t size,
233
const NativeCallStack& stack) {
234
if (tracking_level() < NMT_summary) return;
235
if (addr != NULL) {
236
ThreadCritical tc;
237
if (tracking_level() < NMT_summary) return;
238
VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
239
}
240
}
241
242
// Given an existing memory mapping registered with NMT and a splitting
243
// address, split the mapping in two. The memory region is supposed to
244
// be fully uncommitted.
245
//
246
// The two new memory regions will be both registered under stack and
247
// memory flags of the original region.
248
static inline void record_virtual_memory_split_reserved(void* addr, size_t size, size_t split) {
249
if (tracking_level() < NMT_summary) return;
250
if (addr != NULL) {
251
ThreadCritical tc;
252
// Recheck to avoid potential racing during NMT shutdown
253
if (tracking_level() < NMT_summary) return;
254
VirtualMemoryTracker::split_reserved_region((address)addr, size, split);
255
}
256
}
257
258
static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) {
259
if (tracking_level() < NMT_summary) return;
260
if (addr != NULL) {
261
ThreadCritical tc;
262
if (tracking_level() < NMT_summary) return;
263
VirtualMemoryTracker::set_reserved_region_type((address)addr, flag);
264
}
265
}
266
267
static void record_thread_stack(void* addr, size_t size) {
268
if (tracking_level() < NMT_summary) return;
269
if (addr != NULL) {
270
ThreadStackTracker::new_thread_stack((address)addr, size, CALLER_PC);
271
}
272
}
273
274
static inline void release_thread_stack(void* addr, size_t size) {
275
if (tracking_level() < NMT_summary) return;
276
if (addr != NULL) {
277
ThreadStackTracker::delete_thread_stack((address)addr, size);
278
}
279
}
280
281
// Query lock is used to synchronize the access to tracking data.
282
// So far, it is only used by JCmd query, but it may be used by
283
// other tools.
284
static inline Mutex* query_lock() {
285
assert(NMTQuery_lock != NULL, "not initialized!");
286
return NMTQuery_lock;
287
}
288
289
// Report during error reporting.
290
static void error_report(outputStream* output);
291
292
// Report when handling PrintNMTStatistics before VM shutdown.
293
static void final_report(outputStream* output);
294
295
// Stored baseline
296
static inline MemBaseline& get_baseline() {
297
return _baseline;
298
}
299
300
static NMT_TrackingLevel cmdline_tracking_level() {
301
return _cmdline_tracking_level;
302
}
303
304
static void tuning_statistics(outputStream* out);
305
306
private:
307
static NMT_TrackingLevel init_tracking_level();
308
static void report(bool summary_only, outputStream* output, size_t scale);
309
310
private:
311
// Tracking level
312
static volatile NMT_TrackingLevel _tracking_level;
313
// If NMT option value passed by launcher through environment
314
// variable is valid
315
static bool _is_nmt_env_valid;
316
// command line tracking level
317
static NMT_TrackingLevel _cmdline_tracking_level;
318
// Stored baseline
319
static MemBaseline _baseline;
320
// Query lock
321
static Mutex* _query_lock;
322
};
323
324
#endif // INCLUDE_NMT
325
326
#endif // SHARE_SERVICES_MEMTRACKER_HPP
327
328