Skip to content

Commit 23838a0

Browse files
committed
Implement dynamic MemTag creation
1 parent c11893c commit 23838a0

40 files changed

+592
-231
lines changed

src/hotspot/os/posix/perfMemory_posix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ static char* mmap_create_shared(size_t size) {
10851085
static void unmap_shared(char* addr, size_t bytes) {
10861086
int res;
10871087
if (MemTracker::enabled()) {
1088-
MemTracker::NmtVirtualMemoryLocker nvml;
1088+
NmtVirtualMemoryLocker nvml;
10891089
res = ::munmap(addr, bytes);
10901090
if (res == 0) {
10911091
MemTracker::record_virtual_memory_release(addr, bytes);

src/hotspot/os/windows/perfMemory_windows.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,7 @@ void PerfMemory::detach(char* addr, size_t bytes) {
18001800

18011801
if (MemTracker::enabled()) {
18021802
// it does not go through os api, the operation has to record from here
1803-
MemTracker::NmtVirtualMemoryLocker nvml;
1803+
NmtVirtualMemoryLocker nvml;
18041804
remove_file_mapping(addr);
18051805
MemTracker::record_virtual_memory_release(addr, bytes);
18061806
} else {

src/hotspot/share/gc/z/zNMT.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void ZNMT::unreserve(zaddress_unsafe start, size_t size) {
4747
// We are the owner of the reserved memory, and any failure to unreserve
4848
// are fatal, so so we don't need to hold a lock while unreserving memory.
4949

50-
MemTracker::NmtVirtualMemoryLocker nvml;
50+
NmtVirtualMemoryLocker nvml;
5151

5252
// The current NMT implementation does not support unreserving a memory
5353
// region that was built up from smaller memory reservations. Workaround

src/hotspot/share/jfr/periodic/jfrNativeMemoryEvent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void JfrNativeMemoryEvent::send_type_events(const Ticks& timestamp) {
7878

7979
NMTUsage* usage = get_usage(timestamp);
8080

81-
for (int index = 0; index < mt_number_of_tags; index ++) {
81+
for (int index = 0; index < MemTagFactory::number_of_tags(); index ++) {
8282
MemTag mem_tag = NMTUtil::index_to_tag(index);
8383
if (mem_tag == mtNone) {
8484
// Skip mtNone since it is not really used.

src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,14 @@ void CompilerTypeConstant::serialize(JfrCheckpointWriter& writer) {
348348
}
349349

350350
void NMTTypeConstant::serialize(JfrCheckpointWriter& writer) {
351-
writer.write_count(mt_number_of_tags);
352-
for (int i = 0; i < mt_number_of_tags; ++i) {
351+
writer.write_count(MemTagFactory::number_of_tags());
352+
for (int i = 0; i < MemTagFactory::number_of_tags(); ++i) {
353353
writer.write_key(i);
354354
MemTag mem_tag = NMTUtil::index_to_tag(i);
355-
writer.write(NMTUtil::tag_to_name(mem_tag));
355+
const char* name = MemTagFactory::human_readable_name_of(mem_tag);
356+
if (name == nullptr) {
357+
name = MemTagFactory::name_of(mem_tag);
358+
}
359+
writer.write(name);
356360
}
357361
}

src/hotspot/share/nmt/mallocLimit.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@
2525

2626
#include "nmt/mallocLimit.hpp"
2727
#include "nmt/memTag.hpp"
28+
#include "nmt/memTagFactory.hpp"
2829
#include "nmt/nmtCommon.hpp"
2930
#include "runtime/java.hpp"
3031
#include "runtime/globals.hpp"
3132
#include "utilities/globalDefinitions.hpp"
3233
#include "utilities/parseInteger.hpp"
3334
#include "utilities/ostream.hpp"
3435

35-
MallocLimitSet MallocLimitHandler::_limits;
36+
Deferred<MallocLimitSet> MallocLimitHandler::_limits;
3637
bool MallocLimitHandler::_have_limit = false;
3738

3839
static const char* const MODE_OOM = "oom";
@@ -89,7 +90,7 @@ class ParserHelper {
8990
}
9091
stringStream ss;
9192
ss.print("%.*s", (int)(end - _p), _p);
92-
MemTag mem_tag = NMTUtil::string_to_mem_tag(ss.base());
93+
MemTag mem_tag = MemTagFactory::tag(ss.freeze());
9394
if (mem_tag != mtNone) {
9495
*out = mem_tag;
9596
_p = end;
@@ -132,28 +133,29 @@ void MallocLimitSet::set_global_limit(size_t s, MallocLimitMode flag) {
132133

133134
void MallocLimitSet::set_category_limit(MemTag mem_tag, size_t s, MallocLimitMode flag) {
134135
const int i = NMTUtil::tag_to_index(mem_tag);
135-
_cat[i].sz = s; _cat[i].mode = flag;
136+
malloclimit& tag_limit = _cat.at_grow(i);
137+
tag_limit.sz = s; tag_limit.mode = flag;
136138
}
137139

138140
void MallocLimitSet::reset() {
139141
set_global_limit(0, MallocLimitMode::trigger_fatal);
140142
_glob.sz = 0; _glob.mode = MallocLimitMode::trigger_fatal;
141-
for (int i = 0; i < mt_number_of_tags; i++) {
143+
for (int i = 0; i < MemTagFactory::number_of_tags(); i++) {
142144
set_category_limit(NMTUtil::index_to_tag(i), 0, MallocLimitMode::trigger_fatal);
143145
}
144146
}
145147

146-
void MallocLimitSet::print_on(outputStream* st) const {
148+
void MallocLimitSet::print_on(outputStream* st) {
147149
static const char* flagnames[] = { MODE_FATAL, MODE_OOM };
148150
if (_glob.sz > 0) {
149151
st->print_cr("MallocLimit: total limit: " PROPERFMT " (%s)", PROPERFMTARGS(_glob.sz),
150152
mode_to_name(_glob.mode));
151153
} else {
152-
for (int i = 0; i < mt_number_of_tags; i++) {
153-
if (_cat[i].sz > 0) {
154+
for (int i = 0; i < MemTagFactory::number_of_tags(); i++) {
155+
if (_cat.at_grow(i).sz > 0) {
154156
st->print_cr("MallocLimit: category \"%s\" limit: " PROPERFMT " (%s)",
155-
NMTUtil::tag_to_enum_name(NMTUtil::index_to_tag(i)),
156-
PROPERFMTARGS(_cat[i].sz), mode_to_name(_cat[i].mode));
157+
MemTagFactory::name_of(NMTUtil::index_to_tag(i)),
158+
PROPERFMTARGS(_cat.at_grow(i).sz), mode_to_name(_cat.at_grow(i).mode));
157159
}
158160
}
159161
}
@@ -192,7 +194,7 @@ bool MallocLimitSet::parse_malloclimit_option(const char* v, const char** err) {
192194
BAIL_UNLESS(sst.match_category(&mem_tag), "Expected category name");
193195
BAIL_UNLESS(sst.match_char(':'), "Expected colon following category");
194196

195-
malloclimit* const modified_limit = &_cat[NMTUtil::tag_to_index(mem_tag)];
197+
malloclimit* const modified_limit = &_cat.at_grow(NMTUtil::tag_to_index(mem_tag));
196198

197199
// Match size
198200
BAIL_UNLESS(sst.match_size(&modified_limit->sz), "Expected size");
@@ -213,9 +215,10 @@ bool MallocLimitSet::parse_malloclimit_option(const char* v, const char** err) {
213215

214216
void MallocLimitHandler::initialize(const char* options) {
215217
_have_limit = false;
218+
_limits.initialize();
216219
if (options != nullptr && options[0] != '\0') {
217220
const char* err = nullptr;
218-
if (!_limits.parse_malloclimit_option(options, &err)) {
221+
if (!_limits->parse_malloclimit_option(options, &err)) {
219222
vm_exit_during_initialization("Failed to parse MallocLimit", err);
220223
}
221224
_have_limit = true;
@@ -224,7 +227,7 @@ void MallocLimitHandler::initialize(const char* options) {
224227

225228
void MallocLimitHandler::print_on(outputStream* st) {
226229
if (have_limit()) {
227-
_limits.print_on(st);
230+
_limits->print_on(st);
228231
} else {
229232
st->print_cr("MallocLimit: unset");
230233
}

src/hotspot/share/nmt/mallocLimit.hpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828

2929
#include "memory/allStatic.hpp"
3030
#include "nmt/memTag.hpp"
31+
#include "nmt/nmtCommon.hpp"
3132
#include "utilities/debug.hpp"
33+
#include "utilities/deferred.hpp"
3234
#include "utilities/globalDefinitions.hpp"
35+
#include "utilities/growableArray.hpp"
3336

3437
enum class MallocLimitMode {
3538
trigger_fatal = 0,
@@ -39,14 +42,23 @@ enum class MallocLimitMode {
3942
struct malloclimit {
4043
size_t sz; // Limit size
4144
MallocLimitMode mode; // Behavior flags
45+
46+
malloclimit() : sz(0), mode(MallocLimitMode::trigger_fatal) {}
47+
malloclimit& operator=(const malloclimit& other) {
48+
this->sz = other.sz; this->mode = other.mode;
49+
return *this;
50+
}
51+
malloclimit(const malloclimit& other) {
52+
*this = other;
53+
}
4254
};
4355

4456
// forward declaration
4557
class outputStream;
4658

4759
class MallocLimitSet {
48-
malloclimit _glob; // global limit
49-
malloclimit _cat[mt_number_of_tags]; // per-category limit
60+
malloclimit _glob; // global limit
61+
GrowableArrayCHeap<malloclimit, mtNMT> _cat; // per-category limit
5062
public:
5163
MallocLimitSet();
5264

@@ -57,19 +69,22 @@ class MallocLimitSet {
5769
void set_category_limit(MemTag mem_tag, size_t s, MallocLimitMode mode);
5870

5971
const malloclimit* global_limit() const { return &_glob; }
60-
const malloclimit* category_limit(MemTag mem_tag) const { return &_cat[(int)mem_tag]; }
72+
const malloclimit* category_limit(MemTag mem_tag) {
73+
_cat.at_grow(NMTUtil::tag_to_index(mem_tag));
74+
return &_cat.at(NMTUtil::tag_to_index(mem_tag));
75+
}
6176

62-
void print_on(outputStream* st) const;
77+
void print_on(outputStream* st);
6378
};
6479

6580
class MallocLimitHandler : public AllStatic {
66-
static MallocLimitSet _limits;
81+
static Deferred<MallocLimitSet> _limits;
6782
static bool _have_limit; // shortcut
6883

6984
public:
7085

71-
static const malloclimit* global_limit() { return _limits.global_limit(); }
72-
static const malloclimit* category_limit(MemTag mem_tag) { return _limits.category_limit(mem_tag); }
86+
static const malloclimit* global_limit() { return _limits->global_limit(); }
87+
static const malloclimit* category_limit(MemTag mem_tag) { return _limits->category_limit(mem_tag); }
7388

7489
static void initialize(const char* options);
7590
static void print_on(outputStream* st);

src/hotspot/share/nmt/mallocTracker.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,29 @@ void MemoryCounter::update_peak(size_t size, size_t cnt) {
6363
}
6464
}
6565

66-
void MallocMemorySnapshot::copy_to(MallocMemorySnapshot* s) {
66+
void MallocMemorySnapshot::copy_to(MallocMemorySnapshot** result) {
6767
// Use lock to make sure that mtChunks don't get deallocated while the
6868
// copy is going on, because their size is adjusted using this
6969
// buffer in make_adjustment().
70+
MallocMemorySnapshot* s = new MallocMemorySnapshot(*this);
7071
ChunkPoolLocker lock;
7172
s->_all_mallocs = _all_mallocs;
7273
size_t total_size = 0;
7374
size_t total_count = 0;
74-
for (int index = 0; index < mt_number_of_tags; index ++) {
75+
for (int index = 0; index <MemTagFactory::number_of_tags(); index ++) {
7576
s->_malloc[index] = _malloc[index];
7677
total_size += s->_malloc[index].malloc_size();
7778
total_count += s->_malloc[index].malloc_count();
7879
}
7980
// malloc counters may be updated concurrently
8081
s->_all_mallocs.set_size_and_count(total_size, total_count);
82+
*result = s;
8183
}
8284

8385
// Total malloc'd memory used by arenas
8486
size_t MallocMemorySnapshot::total_arena() const {
8587
size_t amount = 0;
86-
for (int index = 0; index < mt_number_of_tags; index ++) {
88+
for (int index = 0; index < MemTagFactory::number_of_tags(); index ++) {
8789
amount += _malloc[index].arena_size();
8890
}
8991
return amount;
@@ -137,7 +139,7 @@ bool MallocMemorySummary::category_limit_reached(MemTag mem_tag, size_t s, size_
137139

138140
#define FORMATTED \
139141
"MallocLimit: reached category \"%s\" limit (triggering allocation size: " PROPERFMT ", allocated so far: " PROPERFMT ", limit: " PROPERFMT ") ", \
140-
NMTUtil::tag_to_enum_name(mem_tag), PROPERFMTARGS(s), PROPERFMTARGS(so_far), PROPERFMTARGS(limit->sz)
142+
MemTagFactory::name_of(mem_tag), PROPERFMTARGS(s), PROPERFMTARGS(so_far), PROPERFMTARGS(limit->sz)
141143

142144
// If we hit the limit during error reporting, we print a short warning but otherwise ignore it.
143145
// We don't want to risk recursive assertion or torn hs-err logs.
@@ -306,7 +308,7 @@ bool MallocTracker::print_pointer_information(const void* p, outputStream* st) {
306308
p2i(p), where,
307309
(block->is_dead() ? "dead" : "live"),
308310
p2i(block + 1), // lets print the payload start, not the header
309-
block->size(), NMTUtil::tag_to_enum_name(block->mem_tag()));
311+
block->size(), MemTagFactory::name_of(block->mem_tag()));
310312
if (MemTracker::tracking_level() == NMT_detail) {
311313
NativeCallStack ncs;
312314
if (MallocSiteTable::access_stack(ncs, *block)) {

src/hotspot/share/nmt/mallocTracker.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class MallocMemorySnapshot : public CHeapObj<mtNMT> {
228228
// Total malloc'd memory used by arenas
229229
size_t total_arena() const;
230230

231-
void copy_to(MallocMemorySnapshot* s);
231+
void copy_to(MallocMemorySnapshot** s);
232232

233233
// Make adjustment by subtracting chunks used by arenas
234234
// from total chunks to get total free chunk size
@@ -283,7 +283,7 @@ class MallocMemorySummary : AllStatic {
283283

284284
static void snapshot(MallocMemorySnapshot** s) {
285285
*s = new MallocMemorySnapshot(*as_snapshot());
286-
as_snapshot()->copy_to(*s);
286+
as_snapshot()->copy_to(s);
287287
(*s)->make_adjustment();
288288
}
289289

src/hotspot/share/nmt/memBaseline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void MemBaseline::baseline_summary() {
140140
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
141141
VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
142142
{
143-
MemTracker::NmtVirtualMemoryLocker nvml;
143+
NmtVirtualMemoryLocker nvml;
144144
MemoryFileTracker::Instance::summary_snapshot(&_virtual_memory_snapshot);
145145
}
146146

src/hotspot/share/nmt/memMapPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static const char* get_shortname_for_mem_tag(MemTag mem_tag) {
7070
#define DO(t, shortname, text) if (t == mem_tag) return shortname;
7171
NMT_FLAGS_DO(DO)
7272
#undef DO
73-
return NMTUtil::tag_to_enum_name(mem_tag);
73+
return MemTagFactory::name_of(mem_tag);
7474
}
7575

7676
/// NMT virtual memory
@@ -249,7 +249,7 @@ bool MappingPrintSession::print_nmt_info_for_region(const void* vma_from, const
249249
// Correlate vma region (from, to) with NMT region(s) we collected previously.
250250
const MemTagBitmap flags = _nmt_info.lookup(vma_from, vma_to);
251251
if (flags.has_any()) {
252-
for (int i = 0; i < mt_number_of_tags; i++) {
252+
for (int i = 0; i < MemTagFactory::number_of_tags(); i++) {
253253
const MemTag mem_tag = (MemTag)i;
254254
if (flags.has_tag(mem_tag)) {
255255
if (num_printed > 0) {

src/hotspot/share/nmt/memReporter.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void MemReporterBase::print_malloc(const MemoryCounter* c, MemTag mem_tag) const
8080

8181
if (mem_tag != mtNone) {
8282
out->print("(%s%zu%s tag=%s", alloc_type,
83-
amount_in_current_scale(amount), scale, NMTUtil::tag_to_name(mem_tag));
83+
amount_in_current_scale(amount), scale, MemTagFactory::human_readable_name_of(mem_tag));
8484
} else {
8585
out->print("(%s%zu%s", alloc_type,
8686
amount_in_current_scale(amount), scale);
@@ -177,7 +177,7 @@ void MemSummaryReporter::report() {
177177
out->cr();
178178

179179
// Summary by memory tag
180-
for (int index = 0; index < mt_number_of_tags; index ++) {
180+
for (int index = 0; index < MemTagFactory::number_of_tags(); index ++) {
181181
MemTag mem_tag = NMTUtil::index_to_tag(index);
182182
// thread stack is reported as part of thread category
183183
if (mem_tag == mtThreadStack) continue;
@@ -219,7 +219,7 @@ void MemSummaryReporter::report_summary_of_tag(MemTag mem_tag,
219219
outputStream* out = output();
220220
const char* scale = current_scale();
221221
constexpr int indent = 28;
222-
out->print("-%*s (", indent - 2, NMTUtil::tag_to_name(mem_tag));
222+
out->print("-%*s (", indent - 2, MemTagFactory::human_readable_name_of(mem_tag));
223223
print_total(reserved_amount, committed_amount);
224224
#if INCLUDE_CDS
225225
if (mem_tag == mtClassShared) {
@@ -380,7 +380,7 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() {
380380
print_total(virtual_memory_site->reserved(), virtual_memory_site->committed());
381381
const MemTag mem_tag = virtual_memory_site->mem_tag();
382382
if (mem_tag != mtNone) {
383-
out->print(" Tag=%s", NMTUtil::tag_to_name(mem_tag));
383+
out->print(" Tag=%s", MemTagFactory::human_readable_name_of(mem_tag));
384384
}
385385
out->print_cr(")");
386386
)
@@ -423,7 +423,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
423423
const char* region_type = (all_committed ? "reserved and committed" : "reserved");
424424
out->cr();
425425
print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size());
426-
out->print(" for %s", NMTUtil::tag_to_name(reserved_rgn->mem_tag()));
426+
out->print(" for %s", MemTagFactory::human_readable_name_of(reserved_rgn->mem_tag()));
427427
if (stack->is_empty()) {
428428
out->cr();
429429
} else {
@@ -465,7 +465,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
465465
void MemDetailReporter::report_memory_file_allocations() {
466466
stringStream st;
467467
{
468-
MemTracker::NmtVirtualMemoryLocker nvml;
468+
NmtVirtualMemoryLocker nvml;
469469
MemoryFileTracker::Instance::print_all_reports_on(&st, scale());
470470
}
471471
output()->print_raw(st.freeze());
@@ -520,7 +520,7 @@ void MemSummaryDiffReporter::report_diff() {
520520
out->cr();
521521

522522
// Summary diff by memory tag
523-
for (int index = 0; index < mt_number_of_tags; index ++) {
523+
for (int index = 0; index < MemTagFactory::number_of_tags(); index ++) {
524524
MemTag mem_tag = NMTUtil::index_to_tag(index);
525525
// thread stack is reported as part of thread category
526526
if (mem_tag == mtThreadStack) continue;
@@ -543,7 +543,7 @@ void MemSummaryDiffReporter::print_malloc_diff(size_t current_amount, size_t cur
543543
out->print("%s%zu%s", alloc_tag, amount_in_current_scale(current_amount), scale);
544544
// Report type only if it is valid and not under "thread" category
545545
if (mem_tag != mtNone && mem_tag != mtThread) {
546-
out->print(" type=%s", NMTUtil::tag_to_name(mem_tag));
546+
out->print(" type=%s", MemTagFactory::human_readable_name_of(mem_tag));
547547
}
548548

549549
int64_t amount_diff = diff_in_current_scale(current_amount, early_amount);
@@ -636,7 +636,7 @@ void MemSummaryDiffReporter::diff_summary_of_tag(MemTag mem_tag,
636636
diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) {
637637

638638
// print summary line
639-
out->print("-%*s (", indent - 2, NMTUtil::tag_to_name(mem_tag));
639+
out->print("-%*s (", indent - 2, MemTagFactory::human_readable_name_of(mem_tag));
640640
print_virtual_memory_diff(current_reserved_amount, current_committed_amount,
641641
early_reserved_amount, early_committed_amount);
642642
out->print_cr(")");
@@ -937,7 +937,7 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac
937937
out->print("(mmap: ");
938938
print_virtual_memory_diff(current_reserved, current_committed, early_reserved, early_committed);
939939
if (mem_tag != mtNone) {
940-
out->print(" Type=%s", NMTUtil::tag_to_name(mem_tag));
940+
out->print(" Type=%s", MemTagFactory::human_readable_name_of(mem_tag));
941941
}
942942
out->print_cr(")");
943943
)

0 commit comments

Comments
 (0)