8377909: Replace SummaryDiff's array implementation with a hashtable

Reviewed-by: azafari, phubner
This commit is contained in:
Johan Sjölen 2026-02-25 15:14:58 +00:00
parent 194be8180f
commit a3684a7952
8 changed files with 359 additions and 178 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -44,21 +44,21 @@ void MemoryFileTracker::allocate_memory(MemoryFile* file, size_t offset,
VMATree::RegionData regiondata(sidx, mem_tag);
VMATree::SummaryDiff diff;
file->_tree.commit_mapping(offset, size, regiondata, diff);
for (int i = 0; i < mt_number_of_tags; i++) {
VirtualMemory* summary = file->_summary.by_tag(NMTUtil::index_to_tag(i));
summary->reserve_memory(diff.tag[i].commit);
summary->commit_memory(diff.tag[i].commit);
}
diff.visit([&](MemTag mt, const VMATree::SingleDiff& single_diff) {
VirtualMemory* summary = file->_summary.by_tag(mt);
summary->reserve_memory(single_diff.commit);
summary->commit_memory(single_diff.commit);
});
}
void MemoryFileTracker::free_memory(MemoryFile* file, size_t offset, size_t size) {
VMATree::SummaryDiff diff;
file->_tree.release_mapping(offset, size, diff);
for (int i = 0; i < mt_number_of_tags; i++) {
VirtualMemory* summary = file->_summary.by_tag(NMTUtil::index_to_tag(i));
summary->reserve_memory(diff.tag[i].commit);
summary->commit_memory(diff.tag[i].commit);
}
diff.visit([&](MemTag mt, const VMATree::SingleDiff& single_diff) {
VirtualMemory* summary = file->_summary.by_tag(mt);
summary->reserve_memory(single_diff.commit);
summary->commit_memory(single_diff.commit);
});
}
void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* stream, size_t scale) {

View File

@ -80,16 +80,17 @@ void VirtualMemoryTracker::Instance::set_reserved_region_tag(address addr, size_
}
void VirtualMemoryTracker::set_reserved_region_tag(address addr, size_t size, MemTag mem_tag) {
VMATree::SummaryDiff diff = tree()->set_tag((VMATree::position) addr, size, mem_tag);
apply_summary_diff(diff);
VMATree::SummaryDiff diff;
tree()->set_tag((VMATree::position)addr, size, mem_tag, diff);
apply_summary_diff(diff);
}
void VirtualMemoryTracker::Instance::apply_summary_diff(VMATree::SummaryDiff diff) {
void VirtualMemoryTracker::Instance::apply_summary_diff(VMATree::SummaryDiff& diff) {
assert(_tracker != nullptr, "Sanity check");
_tracker->apply_summary_diff(diff);
}
void VirtualMemoryTracker::apply_summary_diff(VMATree::SummaryDiff diff) {
void VirtualMemoryTracker::apply_summary_diff(VMATree::SummaryDiff& diff) {
VMATree::SingleDiff::delta reserve_delta, commit_delta;
size_t reserved, committed;
MemTag tag = mtNone;
@ -104,10 +105,9 @@ void VirtualMemoryTracker::apply_summary_diff(VMATree::SummaryDiff diff) {
#endif
};
for (int i = 0; i < mt_number_of_tags; i++) {
reserve_delta = diff.tag[i].reserve;
commit_delta = diff.tag[i].commit;
tag = NMTUtil::index_to_tag(i);
diff.visit([&](MemTag tag, const VMATree::SingleDiff& single_diff) {
reserve_delta = single_diff.reserve;
commit_delta = single_diff.commit;
reserved = VirtualMemorySummary::as_snapshot()->by_tag(tag)->reserved();
committed = VirtualMemorySummary::as_snapshot()->by_tag(tag)->committed();
if (reserve_delta != 0) {
@ -138,7 +138,7 @@ void VirtualMemoryTracker::apply_summary_diff(VMATree::SummaryDiff diff) {
}
}
}
}
});
}
void VirtualMemoryTracker::Instance::add_committed_region(address addr, size_t size,

View File

@ -309,9 +309,9 @@ class VirtualMemoryTracker {
// Snapshot current thread stacks
void snapshot_thread_stacks();
void apply_summary_diff(VMATree::SummaryDiff diff);
size_t committed_size(const VirtualMemoryRegion* rgn);
address thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn);
void apply_summary_diff(VMATree::SummaryDiff& diff);
size_t committed_size(const VirtualMemoryRegion* rmr);
address thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rmr);
RegionsTree* tree() { return &_tree; }
@ -334,8 +334,8 @@ class VirtualMemoryTracker {
static bool walk_virtual_memory(VirtualMemoryWalker* walker);
static bool print_containing_region(const void* p, outputStream* st);
static void snapshot_thread_stacks();
static void apply_summary_diff(VMATree::SummaryDiff diff);
static size_t committed_size(const VirtualMemoryRegion* rgn);
static void apply_summary_diff(VMATree::SummaryDiff& diff);
static size_t committed_size(const VirtualMemoryRegion* rmr);
// uncommitted thread stack bottom, above guard pages if there is any.
static address thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Red Hat Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -27,6 +27,7 @@
#include "nmt/vmatree.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/powerOfTwo.hpp"
// Semantics
@ -192,8 +193,8 @@ void VMATree::compute_summary_diff(const SingleDiff::delta region_size,
{0,a, 0,a, -a,a }, // op == Commit
{0,0, 0,0, -a,0 } // op == Uncommit
};
SingleDiff& from_rescom = diff.tag[NMTUtil::tag_to_index(current_tag)];
SingleDiff& to_rescom = diff.tag[NMTUtil::tag_to_index(operation_tag)];
SingleDiff& from_rescom = diff.tag(current_tag);
SingleDiff& to_rescom = diff.tag(operation_tag);
int st = state_to_index(ex);
from_rescom.reserve += reserve[op][st * 2 ];
to_rescom.reserve += reserve[op][st * 2 + 1];
@ -657,7 +658,7 @@ void VMATree::print_on(outputStream* out) {
}
#endif
VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, const MemTag tag) {
void VMATree::set_tag(const position start, const size size, const MemTag tag, SummaryDiff& diff) {
auto pos = [](TNode* n) { return n->key(); };
position from = start;
position end = from+size;
@ -689,14 +690,13 @@ VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, con
};
bool success = find_next_range();
if (!success) return SummaryDiff();
if (!success) return;
assert(range.start != nullptr && range.end != nullptr, "must be");
end = MIN2(from + remsize, pos(range.end));
IntervalState& out = out_state(range.start);
StateType type = out.type();
SummaryDiff diff;
// Ignore any released ranges, these must be mtNone and have no stack
if (type != StateType::Released) {
RegionData new_data = RegionData(out.reserved_stack(), tag);
@ -713,7 +713,7 @@ VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, con
// Using register_mapping may invalidate the already found range, so we must
// use find_next_range repeatedly
bool success = find_next_range();
if (!success) return diff;
if (!success) return;
assert(range.start != nullptr && range.end != nullptr, "must be");
end = MIN2(from + remsize, pos(range.end));
@ -729,25 +729,131 @@ VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, con
remsize = remsize - (end - from);
from = end;
}
return diff;
}
#ifdef ASSERT
void VMATree::SummaryDiff::print_on(outputStream* out) {
for (int i = 0; i < mt_number_of_tags; i++) {
if (tag[i].reserve == 0 && tag[i].commit == 0) {
continue;
}
out->print_cr("Tag %s R: " INT64_FORMAT " C: " INT64_FORMAT, NMTUtil::tag_to_enum_name((MemTag)i), tag[i].reserve,
tag[i].commit);
}
visit([&](MemTag mt, const SingleDiff& sd) {
out->print_cr("Tag %s R: " INT64_FORMAT " C: " INT64_FORMAT,
NMTUtil::tag_to_enum_name(mt), sd.reserve, sd.commit);
});
}
#endif
void VMATree::clear() {
_tree.remove_all();
};
}
bool VMATree::is_empty() {
return _tree.size() == 0;
};
}
VMATree::SummaryDiff::KVEntry&
VMATree::SummaryDiff::hash_insert_or_get(const KVEntry& kv, bool* found) {
DEBUG_ONLY(int counter = 0);
// If the length is large (picked as 32)
// then we apply a load-factor check and rehash if it exceeds it.
// When the length is small we're OK with a full linear search for an empty space
// to avoid a grow and rehash.
constexpr float load_factor = 0.5;
constexpr int load_factor_cutoff_length = 32;
if (_length > load_factor_cutoff_length &&
(float)_occupied / _length > load_factor) {
grow_and_rehash();
}
while (true) {
DEBUG_ONLY(counter++);
assert(counter < 8, "Infinite loop?");
int i = hash_to_bucket(kv.mem_tag);
while (i < _length && _members[i].marker == Marker::Occupied) {
if (_members[i].mem_tag == kv.mem_tag) {
// Found previous
*found = true;
return _members[i];
}
i++;
}
*found = false;
// We didn't find it but ran out of space, grow and rehash
// Then look at again
if (i >= _length) {
assert(_length < std::numeric_limits<std::underlying_type_t<MemTag>>::max(), "");
grow_and_rehash();
continue;
}
// We didn't find it, but _members[i] is empty, allocate a new one
assert(_members[i].marker == Marker::Empty, "must be");
_members[i] = kv;
_occupied++;
return _members[i];
}
}
void VMATree::SummaryDiff::grow_and_rehash() {
assert(is_power_of_2(_length), "must be");
constexpr int length_limit = std::numeric_limits<std::underlying_type_t<MemTag>>::max() + 1;
assert(is_power_of_2(length_limit), "must be");
if (_length == length_limit) {
// If we are at MemTag's maximum size, then just continue with the current size.
return;
}
int new_len = _length * 2;
// Save old entries (can't use ResourceMark, too early)
GrowableArrayCHeap<KVEntry, mtNMT> tmp(_length);
for (int i = 0; i < _length; i++) {
tmp.push(_members[i]);
}
// Clear previous -- if applicable
if (_members != _small) {
FREE_C_HEAP_ARRAY(KVEntry, _members);
}
_members = NEW_C_HEAP_ARRAY(KVEntry, new_len, mtNMT);
// Clear new array
memset(_members, 0, sizeof(KVEntry) * new_len);
_length = new_len;
_occupied = 0;
for (int i = 0; i < tmp.length(); i++) {
bool _found = false;
hash_insert_or_get(tmp.at(i), &_found);
}
}
VMATree::SingleDiff& VMATree::SummaryDiff::tag(MemTag tag) {
KVEntry kv{Marker::Occupied, tag, {}};
bool _found = false;
KVEntry& inserted = hash_insert_or_get(kv, &_found);
return inserted.single_diff;
}
VMATree::SingleDiff& VMATree::SummaryDiff::tag(int mt_index) {
return tag((MemTag)mt_index);
}
void VMATree::SummaryDiff::add(const SummaryDiff& other) {
other.visit([&](MemTag mt, const SingleDiff& single_diff) {
bool found = false;
KVEntry other_kv = {Marker::Occupied, mt, single_diff};
KVEntry& this_kv = hash_insert_or_get(other_kv, &found);
if (found) {
this_kv.single_diff.reserve += other_kv.single_diff.reserve;
this_kv.single_diff.commit += other_kv.single_diff.commit;
}
});
}
void VMATree::SummaryDiff::clear() {
if (_members != _small) {
FREE_C_HEAP_ARRAY(KVEntry, _members);
}
memset(_small, 0, sizeof(_small));
}
uint32_t VMATree::SummaryDiff::hash_to_bucket(MemTag mt) {
uint32_t hash = primitive_hash<uint32_t>((uint32_t)mt);
assert(is_power_of_2(_length), "must be");
return hash & ((uint32_t)_length - 1);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -26,6 +26,7 @@
#ifndef SHARE_NMT_VMATREE_HPP
#define SHARE_NMT_VMATREE_HPP
#include "memory/resourceArea.hpp"
#include "nmt/memTag.hpp"
#include "nmt/nmtNativeCallStackStorage.hpp"
#include "utilities/globalDefinitions.hpp"
@ -238,24 +239,57 @@ public:
delta commit;
};
struct SummaryDiff {
SingleDiff tag[mt_number_of_tags];
SummaryDiff() {
class SummaryDiff {
enum class Marker { Empty, Occupied };
static_assert((int)Marker::Empty == 0, "We memset the array to 0, so this must be true");
struct KVEntry {
Marker marker;
MemTag mem_tag;
SingleDiff single_diff;
};
static constexpr const int _init_size = 4;
KVEntry _small[_init_size];
KVEntry* _members;
int _length;
int _occupied;
KVEntry& hash_insert_or_get(const KVEntry& kv, bool* found);
void grow_and_rehash();
uint32_t hash_to_bucket(MemTag mt);
public:
SummaryDiff() : _small(), _members(_small), _length(_init_size), _occupied(0) {
clear();
}
void clear() {
for (int i = 0; i < mt_number_of_tags; i++) {
tag[i] = SingleDiff{0, 0};
~SummaryDiff() {
if (_members != _small) {
FREE_C_HEAP_ARRAY(KVEntry, _members);
}
}
void add(SummaryDiff& other) {
for (int i = 0; i < mt_number_of_tags; i++) {
tag[i].reserve += other.tag[i].reserve;
tag[i].commit += other.tag[i].commit;
SingleDiff& tag(MemTag tag);
SingleDiff& tag(int mt_index);
template<typename F>
void visit(F f) const {
int hits = 0;
for (int i = 0; i < _length; i++) {
const KVEntry& kv = _members[i];
if (kv.marker == Marker::Occupied) {
f(kv.mem_tag, kv.single_diff);
hits++;
}
if (hits == _occupied) {
// Early exit
return;
}
}
}
void add(const SummaryDiff& other);
void clear();
#ifdef ASSERT
void print_on(outputStream* out);
#endif
@ -313,7 +347,7 @@ public:
// partially contained within that interval and set their tag to the one provided.
// This may cause merging and splitting of ranges.
// Released regions are ignored.
SummaryDiff set_tag(position from, size size, MemTag tag);
void set_tag(position from, size size, MemTag tag, SummaryDiff& diff);
void uncommit_mapping(position from, size size, const RegionData& metadata, SummaryDiff& diff) {
register_mapping(from, from + size, StateType::Reserved, metadata, diff, true);

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "nmt/memTag.hpp"
#include "nmt/vmatree.hpp"
#include "unittest.hpp"
// The SummaryDiff is seldom used with a large number of tags
// so test that separately.
TEST(NMTSummaryDiffTest, WorksForLargeTagCount) {
VMATree::SummaryDiff d;
for (int i = 0; i < std::numeric_limits<std::underlying_type_t<MemTag>>::max(); i++) {
VMATree::SingleDiff& sd = d.tag(i);
sd.reserve = i;
}
for (int i = 0; i < std::numeric_limits<std::underlying_type_t<MemTag>>::max(); i++) {
VMATree::SingleDiff& sd = d.tag(i);
EXPECT_EQ(i, sd.reserve);
}
}

View File

@ -44,30 +44,30 @@ TEST_VM_F(NMTRegionsTreeTest, ReserveCommitTwice) {
{
VMATree::SummaryDiff diff;
rt.reserve_mapping(0, 100, rd, diff);
EXPECT_EQ(100, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(100, diff.tag(mtTest).reserve);
}
{
VMATree::SummaryDiff diff, not_used;
rt.commit_region(nullptr, 50, ncs, not_used);
rt.reserve_mapping(0, 100, rd, diff);
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(-50, diff.tag(mtTest).commit);
}
{
VMATree::SummaryDiff diff;
rt.reserve_mapping(0, 100, rd2, diff);
EXPECT_EQ(-100, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(100, diff.tag[NMTUtil::tag_to_index(mtGC)].reserve);
EXPECT_EQ(-100, diff.tag(mtTest).reserve);
EXPECT_EQ(100, diff.tag(mtGC).reserve);
}
{
VMATree::SummaryDiff diff1, diff2;
rt.commit_region(nullptr, 50, ncs, diff1);
EXPECT_EQ(0, diff1.tag[NMTUtil::tag_to_index(mtGC)].reserve);
EXPECT_EQ(50, diff1.tag[NMTUtil::tag_to_index(mtGC)].commit);
EXPECT_EQ(0, diff1.tag(mtGC).reserve);
EXPECT_EQ(50, diff1.tag(mtGC).commit);
rt.commit_region(nullptr, 50, ncs, diff2);
EXPECT_EQ(0, diff2.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(0, diff2.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff2.tag(mtTest).reserve);
EXPECT_EQ(0, diff2.tag(mtTest).commit);
}
}
@ -79,20 +79,20 @@ TEST_VM_F(NMTRegionsTreeTest, CommitUncommitRegion) {
{
VMATree::SummaryDiff diff;
rt.commit_region(nullptr, 50, ncs, diff);
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(50, diff.tag(mtTest).commit);
}
{
VMATree::SummaryDiff diff;
rt.commit_region((address)60, 10, ncs, diff);
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(10, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(10, diff.tag(mtTest).commit);
}
{
VMATree::SummaryDiff diff;
rt.uncommit_region(nullptr, 50, diff);
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(-50, diff.tag(mtTest).commit);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -221,13 +221,13 @@ public:
EXPECT_EQ(n1.val().out.committed_stack(), upd.new_st.committed_stack()) << failed_case;
if (from == to) {
EXPECT_EQ(diff.tag[from].reserve, upd.reserve[0] + upd.reserve[1]) << failed_case;
EXPECT_EQ(diff.tag[from].commit, upd.commit[0] + upd.commit[1]) << failed_case;
EXPECT_EQ(diff.tag(from).reserve, upd.reserve[0] + upd.reserve[1]) << failed_case;
EXPECT_EQ(diff.tag(from).commit, upd.commit[0] + upd.commit[1]) << failed_case;
} else {
EXPECT_EQ(diff.tag[from].reserve, upd.reserve[0]) << failed_case;
EXPECT_EQ(diff.tag[from].commit, upd.commit[0]) << failed_case;
EXPECT_EQ(diff.tag[to].reserve, upd.reserve[1]) << failed_case;
EXPECT_EQ(diff.tag[to].commit, upd.commit[1]) << failed_case;
EXPECT_EQ(diff.tag(from).reserve, upd.reserve[0]) << failed_case;
EXPECT_EQ(diff.tag(from).commit, upd.commit[0]) << failed_case;
EXPECT_EQ(diff.tag(to).reserve, upd.reserve[1]) << failed_case;
EXPECT_EQ(diff.tag(to).commit, upd.commit[1]) << failed_case;
}
}
@ -235,6 +235,7 @@ public:
void create_tree(Tree& tree, ExpectedTree<N>& et, int line_no) {
using SIndex = NativeCallStackStorage::StackIndex;
const SIndex ES = NativeCallStackStorage::invalid; // Empty Stack
VMATree::SummaryDiff not_used;
VMATree::IntervalChange st;
for (int i = 0; i < N; i++) {
st.in.set_type(et.states[i]);
@ -537,8 +538,8 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
tree.reserve_mapping(0, 600, rd, not_used);
tree.set_tag(0, 500, mtGC);
tree.set_tag(500, 100, mtClassShared);
tree.set_tag(0, 500, mtGC, not_used);
tree.set_tag(500, 100, mtClassShared, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -569,8 +570,8 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
tree.commit_mapping(550, 10, rd, not_used);
tree.commit_mapping(565, 10, rd, not_used);
// OK, set tag
tree.set_tag(0, 500, mtGC);
tree.set_tag(500, 100, mtClassShared);
tree.set_tag(0, 500, mtGC, not_used);
tree.set_tag(500, 100, mtClassShared, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -584,7 +585,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
Tree::RegionData compiler(si, mtCompiler);
tree.reserve_mapping(0, 100, gc, not_used);
tree.reserve_mapping(100, 100, compiler, not_used);
tree.set_tag(0, 200, mtGC);
tree.set_tag(0, 200, mtGC, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -601,7 +602,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
Tree::RegionData compiler(si2, mtCompiler);
tree.reserve_mapping(0, 100, gc, not_used);
tree.reserve_mapping(100, 100, compiler, not_used);
tree.set_tag(0, 200, mtGC);
tree.set_tag(0, 200, mtGC, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -615,7 +616,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
VMATree::SummaryDiff not_used;
Tree::RegionData compiler(si, mtCompiler);
tree.reserve_mapping(0, 200, compiler, not_used);
tree.set_tag(100, 50, mtGC);
tree.set_tag(100, 50, mtGC, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -631,7 +632,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
Tree::RegionData compiler(si, mtCompiler);
tree.reserve_mapping(0, 100, gc, not_used);
tree.reserve_mapping(100, 100, compiler, not_used);
tree.set_tag(75, 50, mtClass);
tree.set_tag(75, 50, mtClass, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -647,7 +648,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
Tree::RegionData class_shared(si, mtClassShared);
tree.reserve_mapping(0, 50, class_shared, not_used);
tree.reserve_mapping(75, 25, class_shared, not_used);
tree.set_tag(0, 80, mtGC);
tree.set_tag(0, 80, mtGC, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -659,7 +660,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
VMATree::SummaryDiff not_used;
Tree::RegionData class_shared(si, mtClassShared);
tree.reserve_mapping(10, 10, class_shared, not_used);
tree.set_tag(0, 100, mtCompiler);
tree.set_tag(0, 100, mtCompiler, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
@ -677,7 +678,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) {
tree.reserve_mapping(0, 100, class_shared, not_used);
tree.release_mapping(1, 49, not_used);
tree.release_mapping(75, 24, not_used);
tree.set_tag(0, 100, mtGC);
tree.set_tag(0, 100, mtGC, not_used);
expect_equivalent_form(expected, tree, __LINE__);
}
}
@ -696,7 +697,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff = all_diff.tag(mtTest);
EXPECT_EQ(100, diff.reserve);
tree.reserve_mapping(50, 25, rd_NMT_cs0, all_diff);
// 1 2 3 4 5 6 7 8 9 10 11
@ -707,8 +708,8 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// B - Native Memory Tracking (reserved)
// C - Test (reserved)
// . - free
diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff2 = all_diff.tag[NMTUtil::tag_to_index(mtNMT)];
diff = all_diff.tag(mtTest);
VMATree::SingleDiff diff2 = all_diff.tag(mtNMT);
EXPECT_EQ(-25, diff.reserve);
EXPECT_EQ(25, diff2.reserve);
}
@ -723,14 +724,14 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff = all_diff.tag(mtTest);
EXPECT_EQ(100, diff.reserve);
tree.release_mapping(0, 100, all_diff);
// 1 2 3 4 5 6 7 8 9 10 11
// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
// ..............................................................................................................
// Legend:
diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
diff = all_diff.tag(mtTest);
EXPECT_EQ(-100, diff.reserve);
}
{ // Convert some of a released mapping to a committed one
@ -744,7 +745,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff = all_diff.tag(mtTest);
EXPECT_EQ(diff.reserve, 100);
tree.commit_mapping(0, 100, rd_Test_cs0, all_diff);
// 1 2 3 4 5 6 7 8 9 10 11
@ -753,7 +754,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// a - Test (committed)
// . - free
diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
diff = all_diff.tag(mtTest);
EXPECT_EQ(0, diff.reserve);
EXPECT_EQ(100, diff.commit);
}
@ -768,7 +769,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff = all_diff.tag(mtTest);
EXPECT_EQ(diff.reserve, 10);
tree.reserve_mapping(10, 10, rd_Test_cs0, all_diff);
// 1 2 3
@ -777,7 +778,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
diff = all_diff.tag(mtTest);
EXPECT_EQ(10, diff.reserve);
}
{ // Adjacent reserved mappings with different tags
@ -792,7 +793,7 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// A - Test (reserved)
// . - free
VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
VMATree::SingleDiff diff = all_diff.tag(mtTest);
EXPECT_EQ(diff.reserve, 10);
tree.reserve_mapping(10, 10, rd_NMT_cs0, all_diff);
// 1 2 3
@ -802,9 +803,9 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// A - Test (reserved)
// B - Native Memory Tracking (reserved)
// . - free
diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)];
diff = all_diff.tag(mtTest);
EXPECT_EQ(0, diff.reserve);
diff = all_diff.tag[NMTUtil::tag_to_index(mtNMT)];
diff = all_diff.tag(mtNMT);
EXPECT_EQ(10, diff.reserve);
}
@ -834,8 +835,8 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) {
// Legend:
// a - Test (committed)
// . - free
EXPECT_EQ(16, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(16, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(16, diff.tag(mtTest).commit);
EXPECT_EQ(16, diff.tag(mtTest).reserve);
}
}
@ -845,16 +846,16 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccountingReserveAsUncommit) {
VMATree::SummaryDiff diff1, diff2, diff3;
tree.reserve_mapping(1200, 100, rd, diff1);
tree.commit_mapping(1210, 50, rd, diff2);
EXPECT_EQ(100, diff1.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(50, diff2.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(100, diff1.tag(mtTest).reserve);
EXPECT_EQ(50, diff2.tag(mtTest).commit);
tree.reserve_mapping(1220, 20, rd, diff3);
EXPECT_EQ(-20, diff3.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff3.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(-20, diff3.tag(mtTest).commit);
EXPECT_EQ(0, diff3.tag(mtTest).reserve);
}
// Exceedingly simple tracker for page-granular allocations
// Use it for testing consistency with VMATree.
struct SimpleVMATracker : public CHeapObj<mtTest> {
struct SimpleVMATracker : public CHeapObj<mtTest> {
const size_t page_size = 4096;
enum Kind { Reserved, Committed, Free };
struct Info {
@ -881,10 +882,9 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccountingReserveAsUncommit) {
}
}
VMATree::SummaryDiff do_it(Kind kind, size_t start, size_t size, NativeCallStack stack, MemTag mem_tag) {
void do_it(Kind kind, size_t start, size_t size, NativeCallStack stack, MemTag mem_tag, VMATree::SummaryDiff& diff) {
assert(is_aligned(size, page_size) && is_aligned(start, page_size), "page alignment");
VMATree::SummaryDiff diff;
const size_t page_count = size / page_size;
const size_t start_idx = start / page_size;
const size_t end_idx = start_idx + page_count;
@ -896,34 +896,33 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccountingReserveAsUncommit) {
// Register diff
if (old_info.kind == Reserved) {
diff.tag[(int)old_info.mem_tag].reserve -= page_size;
diff.tag(old_info.mem_tag).reserve -= page_size;
} else if (old_info.kind == Committed) {
diff.tag[(int)old_info.mem_tag].reserve -= page_size;
diff.tag[(int)old_info.mem_tag].commit -= page_size;
diff.tag(old_info.mem_tag).reserve -= page_size;
diff.tag(old_info.mem_tag).commit -= page_size;
}
if (kind == Reserved) {
diff.tag[(int)new_info.mem_tag].reserve += page_size;
diff.tag(new_info.mem_tag).reserve += page_size;
} else if (kind == Committed) {
diff.tag[(int)new_info.mem_tag].reserve += page_size;
diff.tag[(int)new_info.mem_tag].commit += page_size;
diff.tag(new_info.mem_tag).reserve += page_size;
diff.tag(new_info.mem_tag).commit += page_size;
}
// Overwrite old one with new
pages[i] = new_info;
}
return diff;
}
VMATree::SummaryDiff reserve(size_t start, size_t size, NativeCallStack stack, MemTag mem_tag) {
return do_it(Reserved, start, size, stack, mem_tag);
void reserve(size_t start, size_t size, NativeCallStack stack, MemTag mem_tag, VMATree::SummaryDiff& diff) {
return do_it(Reserved, start, size, stack, mem_tag, diff);
}
VMATree::SummaryDiff commit(size_t start, size_t size, NativeCallStack stack, MemTag mem_tag) {
return do_it(Committed, start, size, stack, mem_tag);
void commit(size_t start, size_t size, NativeCallStack stack, MemTag mem_tag, VMATree::SummaryDiff& diff) {
return do_it(Committed, start, size, stack, mem_tag, diff);
}
VMATree::SummaryDiff release(size_t start, size_t size) {
return do_it(Free, start, size, NativeCallStack(), mtNone);
void release(size_t start, size_t size, VMATree::SummaryDiff& diff) {
return do_it(Free, start, size, NativeCallStack(), mtNone, diff);
}
};
@ -979,19 +978,19 @@ TEST_VM_F(NMTVMATreeTest, TestConsistencyWithSimpleTracker) {
VMATree::SummaryDiff tree_diff;
VMATree::SummaryDiff simple_diff;
if (kind == SimpleVMATracker::Reserved) {
simple_diff = tr->reserve(start, size, stack, mem_tag);
tr->reserve(start, size, stack, mem_tag, simple_diff);
tree.reserve_mapping(start, size, data, tree_diff);
} else if (kind == SimpleVMATracker::Committed) {
simple_diff = tr->commit(start, size, stack, mem_tag);
tr->commit(start, size, stack, mem_tag, simple_diff);
tree.commit_mapping(start, size, data, tree_diff);
} else {
simple_diff = tr->release(start, size);
tr->release(start, size, simple_diff);
tree.release_mapping(start, size, tree_diff);
}
for (int j = 0; j < mt_number_of_tags; j++) {
VMATree::SingleDiff td = tree_diff.tag[j];
VMATree::SingleDiff sd = simple_diff.tag[j];
VMATree::SingleDiff td = tree_diff.tag(j);
VMATree::SingleDiff sd = simple_diff.tag(j);
ASSERT_EQ(td.reserve, sd.reserve);
ASSERT_EQ(td.commit, sd.commit);
}
@ -1067,22 +1066,22 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccountingWhenUseTagInplace) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// CCCCCCCCCCCCCCCCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrr
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(25, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(25, diff.tag(mtTest).commit);
tree.commit_mapping(30, 5, rd_None_cs1, diff, true);
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// CCCCCCCCCCCCCCCCCCCCCCCCCrrrrrCCCCCrrrrrrrrrrrrrrr
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(5, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(5, diff.tag(mtTest).commit);
tree.uncommit_mapping(0, 25, rd_None_cs1, diff);
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrCCCCCrrrrrrrrrrrrrrr
EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve);
EXPECT_EQ(-25, diff.tag[NMTUtil::tag_to_index(mtTest)].commit);
EXPECT_EQ(0, diff.tag(mtTest).reserve);
EXPECT_EQ(-25, diff.tag(mtTest).commit);
}
// How the memory regions are visualized:
@ -1328,8 +1327,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows0To3) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCCCCCCC..........................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 10);
ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 25 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl },
@ -1356,8 +1355,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows0To3) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCC...............................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 5);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 5);
ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 20 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl },
@ -1402,8 +1401,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows4to7) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrr..........CCCCCCCCCCCCCCCCCCCC...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 20);
ExpectedTree<4> et = {{ 0, 10, 20, 40 },
{mtNone, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , Rl , C , Rl },
@ -1430,8 +1429,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows4to7) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....rrrrrCCCCCCCCCC...............................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 15);
EXPECT_EQ(diff.tag(mtTest).commit, 10);
EXPECT_EQ(diff.tag(mtTest).reserve, 20 - 15);
ExpectedTree<4> et = {{ 5, 10, 15, 20 },
{mtNone, mtTest, mtTest, mtTest, mtNone},
{Rl , Rs , C , C , Rl },
@ -1458,8 +1457,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows4to7) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrr..CCCCCCCCCCCCCCCCCCCC........................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 10);
ExpectedTree<8> et = {{ 0, 5, 7, 10, 12, 14, 16, 27 },
{mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , Rs , Rl , C , C , C , C , C , Rl },
@ -1486,8 +1485,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows4to7) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrr..CCCCCCCCCCCCC...............................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 13);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 3);
EXPECT_EQ(diff.tag(mtTest).commit, 13);
EXPECT_EQ(diff.tag(mtTest).reserve, 3);
ExpectedTree<8> et = {{ 0, 5, 7, 10, 12, 14, 16, 20 },
{mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , Rs , Rl , C , C , C , C , C , Rl },
@ -1539,8 +1538,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows8to11) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrrCCCCCCCCCCCCCCCCCCCC.....................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 20);
ExpectedTree<3> et = {{ 0, 10, 30 },
{mtNone, mtTest, mtTest, mtNone},
{Rl , Rs , C , Rl },
@ -1567,8 +1566,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows8to11) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// CCCCCCCCCCCCCCCCCCCC...............................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 10);
ExpectedTree<3> et = {{ 0, 10, 20 },
{mtNone, mtTest, mtTest, mtNone},
{Rl , C , C , Rl },
@ -1595,8 +1594,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows8to11) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCCCCCCC..........................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 25 - 20);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 25 - 20);
ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 25 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl },
@ -1623,8 +1622,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows8to11) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCC...............................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 0);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 0);
ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 20 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl },
@ -1670,8 +1669,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows12to15) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 20);
ExpectedTree<4> et = {{ 5, 25, 30, 40 },
{mtNone, mtTest, mtNone, mtTest, mtNone},
{Rl , C , Rl , Rs , Rl },
@ -1698,8 +1697,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows12to15) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCCCCCCCrrrrr.....................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 30 - 25);
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, 30 - 25);
ExpectedTree<4> et = {{ 5, 10, 25, 30 },
{mtNone, mtTest, mtTest, mtTest, mtNone},
{Rl , C , C , Rs , Rl },
@ -1726,8 +1725,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows12to15) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 5) + ( 25 - 20));
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, (10 - 5) + ( 25 - 20));
ExpectedTree<8> et = {{ 5, 10, 12, 14, 16, 25, 30, 40 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl , Rs , Rl },
@ -1754,8 +1753,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows12to15) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// .....CCCCCCCCCCCCCCC..........rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 5);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 10 - 5);
ExpectedTree<8> et = {{ 5, 10, 12, 14, 16, 20, 30, 40 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , C , C , C , C , C , Rl , Rs , Rl },
@ -1800,8 +1799,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows16to19) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrr.....CCCCCCCCCC.....rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10);
EXPECT_EQ(diff.tag(mtTest).commit, 10);
EXPECT_EQ(diff.tag(mtTest).reserve, 10);
ExpectedTree<6> et = {{ 0, 10, 15, 25, 30, 40 },
{mtNone, mtTest, mtNone, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , Rl , C , Rl , Rs , Rl },
@ -1828,8 +1827,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows16to19) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrr.....CCCCCCCCCCrrrrr.....................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 15);
EXPECT_EQ(diff.tag(mtTest).commit, 10);
EXPECT_EQ(diff.tag(mtTest).reserve, 20 - 15);
ExpectedTree<6> et = {{ 0, 10, 15, 20, 25, 30 },
{mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtNone},
{Rl , Rs , Rl , C , C , Rs , Rl },
@ -1856,8 +1855,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows16to19) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrr..CCCCCCCCCCCCCCCCCCCC...rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 7) + (27 - 20));
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, (10 - 7) + (27 - 20));
ExpectedTree<10> et = {{ 0, 5, 7, 12, 14, 16, 20, 27, 30, 40 },
{mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , Rl , C , C , C , C , C , Rl , Rs , Rl },
@ -1884,8 +1883,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows16to19) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrr..CCCCCCCCCCCCC..........rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 13);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 7);
EXPECT_EQ(diff.tag(mtTest).commit, 13);
EXPECT_EQ(diff.tag(mtTest).reserve, 10 - 7);
ExpectedTree<10> et = {{ 0, 5, 7, 10, 12, 14, 16, 20, 30, 40 },
{mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , Rl , C , C , C , C , C , Rl , Rs , Rl },
@ -1931,8 +1930,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows20to23) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrrCCCCCCCCCCCCCCC.....rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 15);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 15);
ExpectedTree<5> et = {{ 0, 10, 25, 30, 40 },
{mtNone, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , C , Rl , Rs , Rl },
@ -1959,8 +1958,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows20to23) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrrrrrrCCCCCCCCCCCCCCCrrrrr.....................
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 10);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 20 - 10);
ExpectedTree<5> et = {{ 0, 10, 20, 25, 30 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtNone},
{Rl , Rs , C , C , Rs , Rl },
@ -1987,8 +1986,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows20to23) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrCCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 5) + (25 - 20));
EXPECT_EQ(diff.tag(mtTest).commit, 20);
EXPECT_EQ(diff.tag(mtTest).reserve, (10 - 5) + (25 - 20));
ExpectedTree<9> et = {{ 0, 5, 12, 14, 16, 20, 25, 30, 40 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , C , C , C , C , C , Rl , Rs , Rl },
@ -2015,8 +2014,8 @@ TEST_VM_F(NMTVMATreeTest, OverlapTableRows20to23) {
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// rrrrrCCCCCCCCCCCCCCC..........rrrrrrrrrr...........
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15);
EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 5);
EXPECT_EQ(diff.tag(mtTest).commit, 15);
EXPECT_EQ(diff.tag(mtTest).reserve, 10 - 5);
ExpectedTree<9> et = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 },
{mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone},
{Rl , Rs , C , C , C , C , C , Rl , Rs , Rl },
@ -2070,4 +2069,4 @@ TEST_VM_F(NMTVMATreeTest, UpdateRegionTest) {
for (auto ci : call_info) {
call_update_region(ci);
}
}
}