Skip to content

Commit 3944e67

Browse files
jdksjolentstuefe
andcommitted
8312132: Add tracking of multiple address spaces in NMT
Co-authored-by: Thomas Stuefe <[email protected]> Reviewed-by: stefank, stuefe
1 parent d0052c0 commit 3944e67

21 files changed

+2271
-105
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
3232
#include "gc/z/zJNICritical.hpp"
3333
#include "gc/z/zLargePages.hpp"
3434
#include "gc/z/zMarkStackAllocator.hpp"
35+
#include "gc/z/zNMT.hpp"
3536
#include "gc/z/zNUMA.hpp"
3637
#include "gc/z/zStat.hpp"
3738
#include "gc/z/zThreadLocalAllocBuffer.hpp"
@@ -46,6 +47,7 @@ ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
4647
VM_Version::jdk_debug_level());
4748

4849
// Early initialization
50+
ZNMT::initialize();
4951
ZGlobalsPointers::initialize();
5052
ZNUMA::initialize();
5153
ZCPU::initialize();

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

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -28,92 +28,31 @@
2828
#include "gc/z/zVirtualMemory.hpp"
2929
#include "nmt/memflags.hpp"
3030
#include "nmt/memTracker.hpp"
31+
#include "nmt/memoryFileTracker.hpp"
3132
#include "utilities/nativeCallStack.hpp"
3233

33-
ZNMT::Reservation ZNMT::_reservations[ZMaxVirtualReservations] = {};
34-
size_t ZNMT::_num_reservations = 0;
34+
MemoryFileTracker::MemoryFile* ZNMT::_device = nullptr;
3535

36-
size_t ZNMT::reservation_index(zoffset offset, size_t* offset_in_reservation) {
37-
assert(_num_reservations > 0, "at least one reservation must exist");
38-
39-
size_t index = 0;
40-
*offset_in_reservation = untype(offset);
41-
for (; index < _num_reservations; ++index) {
42-
const size_t reservation_size = _reservations[index]._size;
43-
if (*offset_in_reservation < reservation_size) {
44-
break;
45-
}
46-
*offset_in_reservation -= reservation_size;
47-
}
48-
49-
assert(index != _num_reservations, "failed to find reservation index");
50-
return index;
51-
}
52-
53-
void ZNMT::process_fake_mapping(zoffset offset, size_t size, bool commit) {
54-
// In order to satisfy NTM's requirement of an 1:1 mapping between committed
55-
// and reserved addresses, a fake mapping from the offset into the reservation
56-
// is used.
57-
//
58-
// These mappings from
59-
// [offset, offset + size) -> {[virtual address range], ...}
60-
// are stable after the heap has been reserved. No commits proceed any
61-
// reservations. Committing and uncommitting the same [offset, offset + size)
62-
// range will result in same virtual memory ranges.
63-
64-
size_t left_to_process = size;
65-
size_t offset_in_reservation;
66-
for (size_t i = reservation_index(offset, &offset_in_reservation); i < _num_reservations; ++i) {
67-
const zaddress_unsafe reservation_start = _reservations[i]._start;
68-
const size_t reservation_size = _reservations[i]._size;
69-
const size_t sub_range_size = MIN2(left_to_process, reservation_size - offset_in_reservation);
70-
const uintptr_t sub_range_addr = untype(reservation_start) + offset_in_reservation;
71-
72-
// commit / uncommit memory
73-
if (commit) {
74-
MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC);
75-
} else {
76-
ThreadCritical tc;
77-
MemTracker::record_virtual_memory_uncommit((address)sub_range_addr, sub_range_size);
78-
}
79-
80-
left_to_process -= sub_range_size;
81-
if (left_to_process == 0) {
82-
// Processed all nmt registrations
83-
return;
84-
}
85-
86-
offset_in_reservation = 0;
87-
}
88-
89-
assert(left_to_process == 0, "everything was not commited");
36+
void ZNMT::initialize() {
37+
_device = MemTracker::register_file("ZGC heap backing file");
9038
}
9139

9240
void ZNMT::reserve(zaddress_unsafe start, size_t size) {
93-
assert(_num_reservations < ZMaxVirtualReservations, "too many reservations");
94-
// Keep track of the reservations made in order to create fake mappings
95-
// between the reserved and commited memory.
96-
// See details in ZNMT::process_fake_mapping
97-
_reservations[_num_reservations++] = {start, size};
98-
99-
MemTracker::record_virtual_memory_reserve((void*)untype(start), size, CALLER_PC, mtJavaHeap);
41+
MemTracker::record_virtual_memory_reserve((address)untype(start), size, CALLER_PC, mtJavaHeap);
10042
}
10143

10244
void ZNMT::commit(zoffset offset, size_t size) {
103-
// NMT expects a 1-to-1 mapping between virtual and physical memory.
104-
// ZGC can temporarily have multiple virtual addresses pointing to
105-
// the same physical memory.
106-
//
107-
// When this function is called we don't know where in the virtual memory
108-
// this physical memory will be mapped. So we fake the virtual memory
109-
// address by mapping the physical offset into offsets in the reserved
110-
// memory space.
111-
process_fake_mapping(offset, size, true);
45+
MemTracker::allocate_memory_in(ZNMT::_device, untype(offset), size, CALLER_PC, mtJavaHeap);
11246
}
11347

11448
void ZNMT::uncommit(zoffset offset, size_t size) {
115-
// We fake the virtual memory address by mapping the physical offset
116-
// into offsets in the reserved memory space.
117-
// See comment in ZNMT::commit
118-
process_fake_mapping(offset, size, false);
49+
MemTracker::free_memory_in(ZNMT::_device, untype(offset), size);
50+
}
51+
52+
void ZNMT::map(zaddress_unsafe addr, size_t size, zoffset offset) {
53+
// NMT doesn't track mappings at the moment.
54+
}
55+
56+
void ZNMT::unmap(zaddress_unsafe addr, size_t size) {
57+
// NMT doesn't track mappings at the moment.
11958
}

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,25 +29,24 @@
2929
#include "gc/z/zMemory.hpp"
3030
#include "gc/z/zVirtualMemory.hpp"
3131
#include "memory/allStatic.hpp"
32+
#include "nmt/memTracker.hpp"
33+
#include "nmt/memoryFileTracker.hpp"
3234
#include "utilities/globalDefinitions.hpp"
3335
#include "utilities/nativeCallStack.hpp"
3436

3537
class ZNMT : public AllStatic {
3638
private:
37-
struct Reservation {
38-
zaddress_unsafe _start;
39-
size_t _size;
40-
};
41-
static Reservation _reservations[ZMaxVirtualReservations];
42-
static size_t _num_reservations;
43-
44-
static size_t reservation_index(zoffset offset, size_t* offset_in_reservation);
45-
static void process_fake_mapping(zoffset offset, size_t size, bool commit);
39+
static MemoryFileTracker::MemoryFile* _device;
4640

4741
public:
42+
static void initialize();
43+
4844
static void reserve(zaddress_unsafe start, size_t size);
4945
static void commit(zoffset offset, size_t size);
5046
static void uncommit(zoffset offset, size_t size);
47+
48+
static void map(zaddress_unsafe addr, size_t size, zoffset offset);
49+
static void unmap(zaddress_unsafe addr, size_t size);
5150
};
5251

5352
#endif // SHARE_GC_Z_ZNMT_HPP

src/hotspot/share/nmt/memBaseline.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,14 @@ class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
137137
}
138138
};
139139

140-
141140
void MemBaseline::baseline_summary() {
142141
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
143142
VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
143+
{
144+
MemoryFileTracker::Instance::Locker lock;
145+
MemoryFileTracker::Instance::summary_snapshot(&_virtual_memory_snapshot);
146+
}
147+
144148
_metaspace_stats = MetaspaceUtils::get_combined_statistics();
145149
}
146150

@@ -189,7 +193,6 @@ void MemBaseline::baseline(bool summaryOnly) {
189193
baseline_allocation_sites();
190194
_baseline_type = Detail_baselined;
191195
}
192-
193196
}
194197

195198
int compare_allocation_site(const VirtualMemoryAllocationSite& s1,

src/hotspot/share/nmt/memReporter.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "nmt/mallocTracker.hpp"
2929
#include "nmt/memflags.hpp"
3030
#include "nmt/memReporter.hpp"
31+
#include "nmt/memoryFileTracker.hpp"
3132
#include "nmt/threadStackTracker.hpp"
3233
#include "nmt/virtualMemoryTracker.hpp"
3334
#include "utilities/globalDefinitions.hpp"
@@ -882,4 +883,13 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac
882883
}
883884

884885
out->print_cr(")\n");
885-
}
886+
}
887+
888+
void MemDetailReporter::report_memory_file_allocations() {
889+
stringStream st;
890+
{
891+
MemoryFileTracker::Instance::Locker lock;
892+
MemoryFileTracker::Instance::print_all_reports_on(&st, scale());
893+
}
894+
output()->print_raw(st.freeze());
895+
}

src/hotspot/share/nmt/memReporter.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@
3030
#include "nmt/memBaseline.hpp"
3131
#include "nmt/nmtCommon.hpp"
3232
#include "nmt/virtualMemoryTracker.hpp"
33-
#include "oops/instanceKlass.hpp"
3433

3534
/*
3635
* Base class that provides helpers
@@ -165,6 +164,7 @@ class MemDetailReporter : public MemSummaryReporter {
165164
virtual void report() {
166165
MemSummaryReporter::report();
167166
report_virtual_memory_map();
167+
report_memory_file_allocations();
168168
report_detail();
169169
}
170170

@@ -173,6 +173,8 @@ class MemDetailReporter : public MemSummaryReporter {
173173
void report_detail();
174174
// Report virtual memory map
175175
void report_virtual_memory_map();
176+
// Report all physical devices
177+
void report_memory_file_allocations();
176178
// Report malloc allocation sites; returns number of omitted sites
177179
int report_malloc_sites();
178180
// Report virtual memory reservation sites; returns number of omitted sites

src/hotspot/share/nmt/memTracker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void MemTracker::initialize() {
6767

6868
if (level > NMT_off) {
6969
if (!MallocTracker::initialize(level) ||
70+
!MemoryFileTracker::Instance::initialize(level) ||
7071
!VirtualMemoryTracker::initialize(level)) {
7172
assert(false, "NMT initialization failed");
7273
level = NMT_off;

src/hotspot/share/nmt/memTracker.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "nmt/mallocTracker.hpp"
2929
#include "nmt/nmtCommon.hpp"
30+
#include "nmt/memoryFileTracker.hpp"
3031
#include "nmt/threadStackTracker.hpp"
3132
#include "nmt/virtualMemoryTracker.hpp"
3233
#include "runtime/mutexLocker.hpp"
@@ -166,6 +167,39 @@ class MemTracker : AllStatic {
166167
}
167168
}
168169

170+
static inline MemoryFileTracker::MemoryFile* register_file(const char* descriptive_name) {
171+
assert_post_init();
172+
if (!enabled()) return nullptr;
173+
MemoryFileTracker::Instance::Locker lock;
174+
return MemoryFileTracker::Instance::make_file(descriptive_name);
175+
}
176+
177+
static inline void remove_file(MemoryFileTracker::MemoryFile* file) {
178+
assert_post_init();
179+
if (!enabled()) return;
180+
assert(file != nullptr, "must be");
181+
MemoryFileTracker::Instance::Locker lock;
182+
MemoryFileTracker::Instance::free_file(file);
183+
}
184+
185+
static inline void allocate_memory_in(MemoryFileTracker::MemoryFile* file, size_t offset, size_t size,
186+
const NativeCallStack& stack, MEMFLAGS flag) {
187+
assert_post_init();
188+
if (!enabled()) return;
189+
assert(file != nullptr, "must be");
190+
MemoryFileTracker::Instance::Locker lock;
191+
MemoryFileTracker::Instance::allocate_memory(file, offset, size, stack, flag);
192+
}
193+
194+
static inline void free_memory_in(MemoryFileTracker::MemoryFile* file,
195+
size_t offset, size_t size) {
196+
assert_post_init();
197+
if (!enabled()) return;
198+
assert(file != nullptr, "must be");
199+
MemoryFileTracker::Instance::Locker lock;
200+
MemoryFileTracker::Instance::free_memory(file, offset, size);
201+
}
202+
169203
// Given an existing memory mapping registered with NMT and a splitting
170204
// address, split the mapping in two. The memory region is supposed to
171205
// be fully uncommitted.

0 commit comments

Comments
 (0)