26
26
#include " precompiled.hpp"
27
27
#include " logging/log.hpp"
28
28
#include " nmt/vmatree.hpp"
29
+ #include " utilities/globalDefinitions.hpp"
29
30
#include " utilities/growableArray.hpp"
30
31
31
32
const VMATree::RegionData VMATree::empty_regiondata{NativeCallStackStorage::StackIndex{}, mtNone};
@@ -82,12 +83,12 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType
82
83
83
84
// Unless we know better, let B's outgoing state be the outgoing state of the node at or preceding A.
84
85
// Consider the case where the found node is the start of a region enclosing [A,B)
85
- stB.out = leqA_n-> val (). out ;
86
+ stB.out = out_state (leqA_n) ;
86
87
87
88
// Direct address match.
88
89
if (leqA_n->key () == A) {
89
90
// Take over in state from old address.
90
- stA.in = leqA_n-> val (). in ;
91
+ stA.in = in_state (leqA_n) ;
91
92
92
93
// We may now be able to merge two regions:
93
94
// If the node's old state matches the new, it becomes a noop. That happens, for example,
@@ -113,7 +114,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType
113
114
// We add a new node, but only if there would be a state change. If there would not be a
114
115
// state change, we just omit the node.
115
116
// That happens, for example, when reserving within an already reserved region with identical metadata.
116
- stA.in = leqA_n-> val (). out ; // .. and the region's prior state is the incoming state
117
+ stA.in = out_state (leqA_n) ; // .. and the region's prior state is the incoming state
117
118
if (stA.is_noop ()) {
118
119
// Nothing to do.
119
120
} else {
@@ -134,7 +135,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType
134
135
// outgoing state.
135
136
_tree.visit_range_in_order (A + 1 , B + 1 , [&](TreapNode* head) {
136
137
int cmp_B = PositionComparator::cmp (head->key (), B);
137
- stB.out = head-> val (). out ;
138
+ stB.out = out_state (head) ;
138
139
if (cmp_B < 0 ) {
139
140
// Record all nodes preceding B.
140
141
to_be_deleted_inbetween_a_b.push ({head->key (), head->val ()});
@@ -215,3 +216,99 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType
215
216
}
216
217
return diff;
217
218
}
219
+
220
+ #ifdef ASSERT
221
+ void VMATree::print_on (outputStream* out) {
222
+ visit_in_order ([&](TreapNode* current) {
223
+ out->print (SIZE_FORMAT " (%s) - %s - " , current->key (), NMTUtil::tag_to_name (out_state (current).mem_tag ()),
224
+ statetype_to_string (out_state (current).type ()));
225
+ });
226
+ out->cr ();
227
+ }
228
+ #endif
229
+
230
+ VMATree::SummaryDiff VMATree::set_tag (const position start, const size size, const MemTag tag) {
231
+ auto pos = [](TreapNode* n) { return n->key (); };
232
+ position from = start;
233
+ position end = from+size;
234
+ size_t remsize = size;
235
+ VMATreap::Range range (nullptr , nullptr );
236
+
237
+ // Find the next range to adjust and set range, remsize and from
238
+ // appropriately. If it returns false, there is no valid next range.
239
+ auto find_next_range = [&]() -> bool {
240
+ range = _tree.find_enclosing_range (from);
241
+ if ((range.start == nullptr && range.end == nullptr ) ||
242
+ (range.start != nullptr && range.end == nullptr )) {
243
+ // There is no range containing the starting address
244
+ assert (range.start ->val ().out .type () == StateType::Released, " must be" );
245
+ return false ;
246
+ } else if (range.start == nullptr && range.end != nullptr ) {
247
+ position found_end = pos (range.end );
248
+ if (found_end >= end) {
249
+ // The found address is outside of our range, we can end now.
250
+ return false ;
251
+ }
252
+ // There is at least one range [found_end, ?) which starts within [start, end)
253
+ // Use this as the range instead.
254
+ range = _tree.find_enclosing_range (found_end);
255
+ remsize = end - found_end;
256
+ from = found_end;
257
+ }
258
+ return true ;
259
+ };
260
+
261
+ bool success = find_next_range ();
262
+ if (!success) return SummaryDiff ();
263
+ assert (range.start != nullptr && range.end != nullptr , " must be" );
264
+
265
+ end = MIN2 (from + remsize, pos (range.end ));
266
+ IntervalState& out = out_state (range.start );
267
+ StateType type = out.type ();
268
+
269
+ SummaryDiff diff;
270
+ // Ignore any released ranges, these must be mtNone and have no stack
271
+ if (type != StateType::Released) {
272
+ RegionData new_data = RegionData (out.stack (), tag);
273
+ SummaryDiff result = register_mapping (from, end, type, new_data);
274
+ diff.add (result);
275
+ }
276
+
277
+ remsize = remsize - (end - from);
278
+ from = end;
279
+
280
+ // If end < from + sz then there are multiple ranges for which to set the flag.
281
+ while (end < from + remsize) {
282
+ // Using register_mapping may invalidate the already found range, so we must
283
+ // use find_next_range repeatedly
284
+ bool success = find_next_range ();
285
+ if (!success) return diff;
286
+ assert (range.start != nullptr && range.end != nullptr , " must be" );
287
+
288
+ end = MIN2 (from + remsize, pos (range.end ));
289
+ IntervalState& out = out_state (range.start );
290
+ StateType type = out.type ();
291
+
292
+ if (type != StateType::Released) {
293
+ RegionData new_data = RegionData (out.stack (), tag);
294
+ SummaryDiff result = register_mapping (from, end, type, new_data);
295
+ diff.add (result);
296
+ }
297
+ remsize = remsize - (end - from);
298
+ from = end;
299
+ }
300
+
301
+ return diff;
302
+ }
303
+
304
+ #ifdef ASSERT
305
+ void VMATree::SummaryDiff::print_on (outputStream* out) {
306
+ for (int i = 0 ; i < mt_number_of_tags; i++) {
307
+ if (tag[i].reserve == 0 && tag[i].commit == 0 ) {
308
+ continue ;
309
+ }
310
+ out->print_cr (" Tag %s R: " INT64_FORMAT " C: " INT64_FORMAT, NMTUtil::tag_to_enum_name ((MemTag)i), tag[i].reserve ,
311
+ tag[i].commit );
312
+ }
313
+ }
314
+ #endif
0 commit comments