Skip to content

Commit 1581508

Browse files
author
Afshin Zafari
committedOct 14, 2024
8335091: NMT: VMATree reserve_mapping and commit_mapping APIs need MEMFLAGS while un/-committing API has no MEMFLAGS arg
Reviewed-by: jsjolen, gziemski
1 parent b20c5c7 commit 1581508

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed
 

‎src/hotspot/share/nmt/vmatree.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525

2626
#include "precompiled.hpp"
27+
#include "logging/log.hpp"
2728
#include "nmt/vmatree.hpp"
2829
#include "utilities/growableArray.hpp"
2930

@@ -34,7 +35,9 @@ const char* VMATree::statetype_strings[3] = {
3435
};
3536

3637
VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType state,
37-
const RegionData& metadata) {
38+
const RegionData& metadata, bool use_tag_inplace) {
39+
assert(!use_tag_inplace || metadata.mem_tag == mtNone,
40+
"If using use_tag_inplace, then the supplied tag should be mtNone, was instead: %s", NMTUtil::tag_to_name(metadata.mem_tag));
3841
if (A == B) {
3942
// A 0-sized mapping isn't worth recording.
4043
return SummaryDiff();
@@ -55,13 +58,28 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType
5558
AddressState LEQ_A;
5659
TreapNode* leqA_n = _tree.closest_leq(A);
5760
if (leqA_n == nullptr) {
61+
assert(!use_tag_inplace, "Cannot use the tag inplace if no pre-existing tag exists. From: " PTR_FORMAT " To: " PTR_FORMAT, A, B);
62+
if (use_tag_inplace) {
63+
log_debug(nmt)("Cannot use the tag inplace if no pre-existing tag exists. From: " PTR_FORMAT " To: " PTR_FORMAT, A, B);
64+
}
5865
// No match. We add the A node directly, unless it would have no effect.
5966
if (!stA.is_noop()) {
6067
_tree.upsert(A, stA);
6168
}
6269
} else {
6370
LEQ_A_found = true;
6471
LEQ_A = AddressState{leqA_n->key(), leqA_n->val()};
72+
StateType leqA_state = leqA_n->val().out.type();
73+
StateType new_state = stA.out.type();
74+
// If we specify use_tag_inplace then the new region takes over the current tag instead of the tag in metadata.
75+
// This is important because the VirtualMemoryTracker API doesn't require supplying the tag for some operations.
76+
if (use_tag_inplace) {
77+
assert(leqA_n->val().out.type() != StateType::Released, "Should not use inplace the tag of a released region");
78+
MemTag tag = leqA_n->val().out.mem_tag();
79+
stA.out.set_tag(tag);
80+
stB.in.set_tag(tag);
81+
}
82+
6583
// Unless we know better, let B's outgoing state be the outgoing state of the node at or preceding A.
6684
// Consider the case where the found node is the start of a region enclosing [A,B)
6785
stB.out = leqA_n->val().out;

‎src/hotspot/share/nmt/vmatree.hpp

+21-11
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class VMATree {
6666
return statetype_strings[static_cast<uint8_t>(type)];
6767
}
6868

69-
// Each point has some stack and a flag associated with it.
69+
// Each point has some stack and a tag associated with it.
7070
struct RegionData {
7171
const NativeCallStackStorage::StackIndex stack_idx;
7272
const MemTag mem_tag;
@@ -88,30 +88,34 @@ class VMATree {
8888
struct IntervalState {
8989
private:
9090
// Store the type and mem_tag as two bytes
91-
uint8_t type_flag[2];
91+
uint8_t type_tag[2];
9292
NativeCallStackStorage::StackIndex sidx;
9393

9494
public:
95-
IntervalState() : type_flag{0,0}, sidx() {}
95+
IntervalState() : type_tag{0,0}, sidx() {}
9696
IntervalState(const StateType type, const RegionData data) {
9797
assert(!(type == StateType::Released) || data.mem_tag == mtNone, "Released type must have memory tag mtNone");
98-
type_flag[0] = static_cast<uint8_t>(type);
99-
type_flag[1] = static_cast<uint8_t>(data.mem_tag);
98+
type_tag[0] = static_cast<uint8_t>(type);
99+
type_tag[1] = static_cast<uint8_t>(data.mem_tag);
100100
sidx = data.stack_idx;
101101
}
102102

103103
StateType type() const {
104-
return static_cast<StateType>(type_flag[0]);
104+
return static_cast<StateType>(type_tag[0]);
105105
}
106106

107107
MemTag mem_tag() const {
108-
return static_cast<MemTag>(type_flag[1]);
108+
return static_cast<MemTag>(type_tag[1]);
109109
}
110110

111111
RegionData regiondata() const {
112112
return RegionData{sidx, mem_tag()};
113113
}
114114

115+
void set_tag(MemTag tag) {
116+
type_tag[1] = static_cast<uint8_t>(tag);
117+
}
118+
115119
NativeCallStackStorage::StackIndex stack() const {
116120
return sidx;
117121
}
@@ -167,14 +171,20 @@ class VMATree {
167171
}
168172
};
169173

170-
SummaryDiff register_mapping(position A, position B, StateType state, const RegionData& metadata);
174+
private:
175+
SummaryDiff register_mapping(position A, position B, StateType state, const RegionData& metadata, bool use_tag_inplace = false);
171176

177+
public:
172178
SummaryDiff reserve_mapping(position from, position sz, const RegionData& metadata) {
173-
return register_mapping(from, from + sz, StateType::Reserved, metadata);
179+
return register_mapping(from, from + sz, StateType::Reserved, metadata, false);
180+
}
181+
182+
SummaryDiff commit_mapping(position from, position sz, const RegionData& metadata, bool use_tag_inplace = false) {
183+
return register_mapping(from, from + sz, StateType::Committed, metadata, use_tag_inplace);
174184
}
175185

176-
SummaryDiff commit_mapping(position from, position sz, const RegionData& metadata) {
177-
return register_mapping(from, from + sz, StateType::Committed, metadata);
186+
SummaryDiff uncommit_mapping(position from, position sz, const RegionData& metadata) {
187+
return register_mapping(from, from + sz, StateType::Reserved, metadata, true);
178188
}
179189

180190
SummaryDiff release_mapping(position from, position sz) {

‎test/hotspot/gtest/nmt/test_vmatree.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ class NMTVMATreeTest : public testing::Test {
171171
};
172172

173173

174-
175174
TEST_VM_F(NMTVMATreeTest, OverlappingReservationsResultInTwoNodes) {
176175
VMATree::RegionData rd{si[0], mtTest};
177176
Tree tree;
@@ -181,6 +180,23 @@ TEST_VM_F(NMTVMATreeTest, OverlappingReservationsResultInTwoNodes) {
181180
EXPECT_EQ(2, count_nodes(tree));
182181
}
183182

183+
TEST_VM_F(NMTVMATreeTest, UseFlagInplace) {
184+
Tree tree;
185+
VMATree::RegionData rd1(si[0], mtTest);
186+
VMATree::RegionData rd2(si[1], mtNone);
187+
tree.reserve_mapping(0, 100, rd1);
188+
tree.commit_mapping(20, 50, rd2, true);
189+
tree.uncommit_mapping(30, 10, rd2);
190+
tree.visit_in_order([&](Node* node) {
191+
if (node->key() != 100) {
192+
EXPECT_EQ(mtTest, node->val().out.mem_tag()) << "failed at: " << node->key();
193+
if (node->key() != 20 && node->key() != 40) {
194+
EXPECT_EQ(VMATree::StateType::Reserved, node->val().out.type());
195+
}
196+
}
197+
});
198+
}
199+
184200
// Low-level tests inspecting the state of the tree.
185201
TEST_VM_F(NMTVMATreeTest, LowLevel) {
186202
adjacent_2_nodes(VMATree::empty_regiondata);

0 commit comments

Comments
 (0)
Please sign in to comment.