mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-27 05:42:24 +00:00
8377996: [REDO] NMT: Consolidate [Virtual/Committed/Reserved]Regions into one structure
Reviewed-by: phubner, jsjolen
This commit is contained in:
parent
35ed56afc7
commit
bc9c6c6af9
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -168,12 +168,13 @@ int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
|
||||
}
|
||||
|
||||
bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
|
||||
|
||||
SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
|
||||
|
||||
VirtualMemoryAllocationSite* site;
|
||||
bool failed_oom = false;
|
||||
_vma_allocations->visit_reserved_regions([&](ReservedMemoryRegion& rgn) {
|
||||
VirtualMemoryAllocationSite tmp(*rgn.call_stack(), rgn.mem_tag());
|
||||
_vma_allocations->visit_reserved_regions([&](VirtualMemoryRegion& rgn) {
|
||||
VirtualMemoryAllocationSite tmp(*rgn.reserved_call_stack(), rgn.mem_tag());
|
||||
site = allocation_sites.find(tmp);
|
||||
if (site == nullptr) {
|
||||
LinkedListNode<VirtualMemoryAllocationSite>* node =
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Red Hat, Inc. and/or its affiliates.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -149,7 +149,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool do_allocation_site(const ReservedMemoryRegion* rgn) override {
|
||||
bool do_allocation_site(const VirtualMemoryRegion* rgn) override {
|
||||
// Cancel iteration if we run out of memory (add returns false);
|
||||
return add(rgn->base(), rgn->end(), rgn->mem_tag());
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -395,14 +395,14 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() {
|
||||
void MemDetailReporter::report_virtual_memory_map() {
|
||||
// Virtual memory map always in base address order
|
||||
output()->print_cr("Virtual memory map:");
|
||||
_baseline.virtual_memory_allocations()->visit_reserved_regions([&](ReservedMemoryRegion& rgn) {
|
||||
_baseline.virtual_memory_allocations()->visit_reserved_regions([&](VirtualMemoryRegion& rgn) {
|
||||
report_virtual_memory_region(&rgn);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) {
|
||||
assert(reserved_rgn != nullptr, "null pointer");
|
||||
void MemDetailReporter::report_virtual_memory_region(const VirtualMemoryRegion* rgn) {
|
||||
assert(rgn != nullptr, "null pointer");
|
||||
|
||||
// We don't bother about reporting peaks here.
|
||||
// That is because peaks - in the context of virtual memory, peak of committed areas - make little sense
|
||||
@ -414,16 +414,16 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
|
||||
// usage *by callsite*.
|
||||
|
||||
// Don't report if size is too small.
|
||||
if (amount_in_current_scale(reserved_rgn->size()) == 0) return;
|
||||
if (amount_in_current_scale(rgn->size()) == 0) return;
|
||||
|
||||
outputStream* out = output();
|
||||
const char* scale = current_scale();
|
||||
const NativeCallStack* stack = reserved_rgn->call_stack();
|
||||
bool all_committed = reserved_rgn->size() == _baseline.virtual_memory_allocations()->committed_size(*reserved_rgn);
|
||||
const NativeCallStack* stack = rgn->reserved_call_stack();
|
||||
bool all_committed = rgn->size() == _baseline.virtual_memory_allocations()->committed_size(*rgn);
|
||||
const char* region_type = (all_committed ? "reserved and committed" : "reserved");
|
||||
out->cr();
|
||||
print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size());
|
||||
out->print(" for %s", NMTUtil::tag_to_name(reserved_rgn->mem_tag()));
|
||||
print_virtual_memory_region(region_type, rgn->base(), rgn->size());
|
||||
out->print(" for %s", NMTUtil::tag_to_name(rgn->mem_tag()));
|
||||
if (stack->is_empty()) {
|
||||
out->cr();
|
||||
} else {
|
||||
@ -433,9 +433,9 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
|
||||
|
||||
if (all_committed) {
|
||||
bool reserved_and_committed = false;
|
||||
_baseline.virtual_memory_allocations()->visit_committed_regions(*reserved_rgn,
|
||||
[&](CommittedMemoryRegion& committed_rgn) {
|
||||
if (committed_rgn.equals(*reserved_rgn)) {
|
||||
_baseline.virtual_memory_allocations()->visit_committed_regions(*rgn,
|
||||
[&](VirtualMemoryRegion& committed_rgn) {
|
||||
if (committed_rgn.equals(*rgn)) {
|
||||
// One region spanning the entire reserved region, with the same stack trace.
|
||||
// Don't print this regions because the "reserved and committed" line above
|
||||
// already indicates that the region is committed.
|
||||
@ -450,13 +450,13 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
|
||||
}
|
||||
}
|
||||
|
||||
auto print_committed_rgn = [&](const CommittedMemoryRegion& crgn) {
|
||||
auto print_committed_rgn = [&](const VirtualMemoryRegion& rgn) {
|
||||
// Don't report if size is too small
|
||||
if (amount_in_current_scale(crgn.size()) == 0) return;
|
||||
stack = crgn.call_stack();
|
||||
if (amount_in_current_scale(rgn.size()) == 0) return;
|
||||
stack = rgn.committed_call_stack();
|
||||
out->cr();
|
||||
INDENT_BY(8,
|
||||
print_virtual_memory_region("committed", crgn.base(), crgn.size());
|
||||
print_virtual_memory_region("committed", rgn.base(), rgn.size());
|
||||
if (stack->is_empty()) {
|
||||
out->cr();
|
||||
} else {
|
||||
@ -466,9 +466,9 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
|
||||
)
|
||||
};
|
||||
|
||||
_baseline.virtual_memory_allocations()->visit_committed_regions(*reserved_rgn,
|
||||
[&](CommittedMemoryRegion& crgn) {
|
||||
print_committed_rgn(crgn);
|
||||
_baseline.virtual_memory_allocations()->visit_committed_regions(*rgn,
|
||||
[&](VirtualMemoryRegion& committed_rgn) {
|
||||
print_committed_rgn(committed_rgn);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -178,7 +178,7 @@ class MemDetailReporter : public MemSummaryReporter {
|
||||
int report_virtual_memory_allocation_sites();
|
||||
|
||||
// Report a virtual memory region
|
||||
void report_virtual_memory_region(const ReservedMemoryRegion* rgn);
|
||||
void report_virtual_memory_region(const VirtualMemoryRegion* rgn);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -58,9 +58,9 @@ void RegionsTree::print_on(outputStream* st) {
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t RegionsTree::committed_size(const ReservedMemoryRegion& rgn) {
|
||||
size_t RegionsTree::committed_size(const VirtualMemoryRegion& rgn) {
|
||||
size_t result = 0;
|
||||
visit_committed_regions(rgn, [&](CommittedMemoryRegion& crgn) {
|
||||
visit_committed_regions(rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
result += crgn.size();
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -29,8 +29,7 @@
|
||||
#include "nmt/vmatree.hpp"
|
||||
|
||||
|
||||
class ReservedMemoryRegion;
|
||||
class CommittedMemoryRegion;
|
||||
class VirtualMemoryRegion;
|
||||
// RegionsTree extends VMATree to add some more specific API and also defines a helper
|
||||
// for processing the tree nodes in a shorter and more meaningful way.
|
||||
class RegionsTree : public VMATree {
|
||||
@ -46,7 +45,7 @@ class RegionsTree : public VMATree {
|
||||
_with_storage(other._with_storage) {}
|
||||
RegionsTree& operator=(const RegionsTree& other) = delete;
|
||||
|
||||
ReservedMemoryRegion find_reserved_region(address addr);
|
||||
VirtualMemoryRegion find_reserved_region(address addr);
|
||||
|
||||
void commit_region(address addr, size_t size, const NativeCallStack& stack, SummaryDiff& diff);
|
||||
void uncommit_region(address addr, size_t size, SummaryDiff& diff);
|
||||
@ -71,6 +70,7 @@ class RegionsTree : public VMATree {
|
||||
return position() - other.position();
|
||||
}
|
||||
inline NativeCallStackStorage::StackIndex out_stack_index() const { return _node->val().out.reserved_stack(); }
|
||||
inline NativeCallStackStorage::StackIndex out_committed_stack_index() const { return _node->val().out.committed_stack(); }
|
||||
inline MemTag in_tag() const { return _node->val().in.mem_tag(); }
|
||||
inline MemTag out_tag() const { return _node->val().out.mem_tag(); }
|
||||
inline void set_in_tag(MemTag tag) { _node->val().in.set_tag(tag); }
|
||||
@ -81,7 +81,7 @@ class RegionsTree : public VMATree {
|
||||
DEBUG_ONLY(void print_on(outputStream* st);)
|
||||
|
||||
template<typename F>
|
||||
void visit_committed_regions(const ReservedMemoryRegion& rgn, F func);
|
||||
void visit_committed_regions(const VirtualMemoryRegion& rgn, F func);
|
||||
|
||||
template<typename F>
|
||||
void visit_reserved_regions(F func);
|
||||
@ -90,7 +90,7 @@ class RegionsTree : public VMATree {
|
||||
return RegionData(_ncs_storage.push(ncs), tag);
|
||||
}
|
||||
|
||||
inline const NativeCallStack stack(NodeHelper& node) {
|
||||
inline const NativeCallStack reserved_stack(NodeHelper& node) {
|
||||
if (!_with_storage) {
|
||||
return NativeCallStack::empty_stack();
|
||||
}
|
||||
@ -98,7 +98,15 @@ class RegionsTree : public VMATree {
|
||||
return _ncs_storage.get(si);
|
||||
}
|
||||
|
||||
size_t committed_size(const ReservedMemoryRegion& rgn);
|
||||
inline const NativeCallStack committed_stack(NodeHelper& node) {
|
||||
if (!_with_storage) {
|
||||
return NativeCallStack::empty_stack();
|
||||
}
|
||||
NativeCallStackStorage::StackIndex si = node.out_committed_stack_index();
|
||||
return _ncs_storage.get(si);
|
||||
}
|
||||
|
||||
size_t committed_size(const VirtualMemoryRegion& rgn);
|
||||
};
|
||||
|
||||
#endif // NMT_REGIONSTREE_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -29,7 +29,7 @@
|
||||
#include "nmt/virtualMemoryTracker.hpp"
|
||||
|
||||
template<typename F>
|
||||
void RegionsTree::visit_committed_regions(const ReservedMemoryRegion& rgn, F func) {
|
||||
void RegionsTree::visit_committed_regions(const VirtualMemoryRegion& rgn, F func) {
|
||||
position start = (position)rgn.base();
|
||||
size_t end = reinterpret_cast<size_t>(rgn.end()) + 1;
|
||||
size_t comm_size = 0;
|
||||
@ -38,8 +38,12 @@ void RegionsTree::visit_committed_regions(const ReservedMemoryRegion& rgn, F fun
|
||||
visit_range_in_order(start, end, [&](Node* node) {
|
||||
NodeHelper curr(node);
|
||||
if (prev.is_valid() && prev.is_committed_begin()) {
|
||||
CommittedMemoryRegion cmr((address)prev.position(), curr.distance_from(prev), stack(prev));
|
||||
if (!func(cmr)) {
|
||||
VirtualMemoryRegion rgn((address)prev.position(),
|
||||
curr.distance_from(prev),
|
||||
reserved_stack(prev),
|
||||
committed_stack(prev),
|
||||
prev.out_tag());
|
||||
if (!func(rgn)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -63,13 +67,13 @@ void RegionsTree::visit_reserved_regions(F func) {
|
||||
}
|
||||
prev = curr;
|
||||
if (curr.is_released_begin() || begin_node.out_tag() != curr.out_tag()) {
|
||||
auto st = stack(begin_node);
|
||||
auto st = reserved_stack(begin_node);
|
||||
if (rgn_size == 0) {
|
||||
prev.clear_node();
|
||||
return true;
|
||||
}
|
||||
ReservedMemoryRegion rmr((address)begin_node.position(), rgn_size, st, begin_node.out_tag());
|
||||
if (!func(rmr)) {
|
||||
VirtualMemoryRegion rgn((address)begin_node.position(), rgn_size, st, begin_node.out_tag());
|
||||
if (!func(rgn)) {
|
||||
return false;
|
||||
}
|
||||
rgn_size = 0;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -193,14 +193,14 @@ bool VirtualMemoryTracker::Instance::print_containing_region(const void* p, outp
|
||||
}
|
||||
|
||||
bool VirtualMemoryTracker::print_containing_region(const void* p, outputStream* st) {
|
||||
ReservedMemoryRegion rmr = tree()->find_reserved_region((address)p);
|
||||
if (!rmr.contain_address((address)p)) {
|
||||
VirtualMemoryRegion rgn = tree()->find_reserved_region((address)p);
|
||||
if (!rgn.is_valid() || !rgn.contain_address((address)p)) {
|
||||
return false;
|
||||
}
|
||||
st->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "], tag %s",
|
||||
p2i(p), p2i(rmr.base()), p2i(rmr.end()), NMTUtil::tag_to_enum_name(rmr.mem_tag()));
|
||||
p2i(p), p2i(rgn.base()), p2i(rgn.end()), NMTUtil::tag_to_enum_name(rgn.mem_tag()));
|
||||
if (MemTracker::tracking_level() == NMT_detail) {
|
||||
rmr.call_stack()->print_on(st);
|
||||
rgn.reserved_call_stack()->print_on(st);
|
||||
}
|
||||
st->cr();
|
||||
return true;
|
||||
@ -213,7 +213,7 @@ bool VirtualMemoryTracker::Instance::walk_virtual_memory(VirtualMemoryWalker* wa
|
||||
|
||||
bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
||||
bool ret = true;
|
||||
tree()->visit_reserved_regions([&](ReservedMemoryRegion& rgn) {
|
||||
tree()->visit_reserved_regions([&](VirtualMemoryRegion& rgn) {
|
||||
if (!walker->do_allocation_site(&rgn)) {
|
||||
ret = false;
|
||||
return false;
|
||||
@ -223,29 +223,29 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t VirtualMemoryTracker::committed_size(const ReservedMemoryRegion* rmr) {
|
||||
size_t VirtualMemoryTracker::committed_size(const VirtualMemoryRegion* rgn) {
|
||||
size_t result = 0;
|
||||
tree()->visit_committed_regions(*rmr, [&](CommittedMemoryRegion& crgn) {
|
||||
tree()->visit_committed_regions(*rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
result += crgn.size();
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t VirtualMemoryTracker::Instance::committed_size(const ReservedMemoryRegion* rmr) {
|
||||
size_t VirtualMemoryTracker::Instance::committed_size(const VirtualMemoryRegion* rgn) {
|
||||
assert(_tracker != nullptr, "Sanity check");
|
||||
return _tracker->committed_size(rmr);
|
||||
return _tracker->committed_size(rgn);
|
||||
}
|
||||
|
||||
address VirtualMemoryTracker::Instance::thread_stack_uncommitted_bottom(const ReservedMemoryRegion* rmr) {
|
||||
address VirtualMemoryTracker::Instance::thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn) {
|
||||
assert(_tracker != nullptr, "Sanity check");
|
||||
return _tracker->thread_stack_uncommitted_bottom(rmr);
|
||||
return _tracker->thread_stack_uncommitted_bottom(rgn);
|
||||
}
|
||||
|
||||
address VirtualMemoryTracker::thread_stack_uncommitted_bottom(const ReservedMemoryRegion* rmr) {
|
||||
address bottom = rmr->base();
|
||||
address top = rmr->end();
|
||||
tree()->visit_committed_regions(*rmr, [&](CommittedMemoryRegion& crgn) {
|
||||
address VirtualMemoryTracker::thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn) {
|
||||
address bottom = rgn->base();
|
||||
address top = rgn->end();
|
||||
tree()->visit_committed_regions(*rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
address committed_top = crgn.base() + crgn.size();
|
||||
if (committed_top < top) {
|
||||
// committed stack guard pages, skip them
|
||||
@ -299,7 +299,7 @@ class SnapshotThreadStackWalker : public VirtualMemoryWalker {
|
||||
public:
|
||||
SnapshotThreadStackWalker() {}
|
||||
|
||||
bool do_allocation_site(const ReservedMemoryRegion* rgn) {
|
||||
bool do_allocation_site(const VirtualMemoryRegion* rgn) {
|
||||
if (MemTracker::NmtVirtualMemoryLocker::is_safe_to_use()) {
|
||||
assert_lock_strong(NmtVirtualMemory_lock);
|
||||
}
|
||||
@ -340,19 +340,19 @@ void VirtualMemoryTracker::Instance::snapshot_thread_stacks() {
|
||||
walk_virtual_memory(&walker);
|
||||
}
|
||||
|
||||
ReservedMemoryRegion RegionsTree::find_reserved_region(address addr) {
|
||||
ReservedMemoryRegion rmr;
|
||||
auto contain_region = [&](ReservedMemoryRegion& region_in_tree) {
|
||||
VirtualMemoryRegion RegionsTree::find_reserved_region(address addr) {
|
||||
VirtualMemoryRegion rgn;
|
||||
auto contain_region = [&](VirtualMemoryRegion& region_in_tree) {
|
||||
if (region_in_tree.contain_address(addr)) {
|
||||
rmr = region_in_tree;
|
||||
rgn = region_in_tree;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
visit_reserved_regions(contain_region);
|
||||
return rmr;
|
||||
return rgn;
|
||||
}
|
||||
|
||||
bool CommittedMemoryRegion::equals(const ReservedMemoryRegion& rmr) const {
|
||||
return size() == rmr.size() && call_stack()->equals(*(rmr.call_stack()));
|
||||
bool VirtualMemoryRegion::equals_including_stacks(const VirtualMemoryRegion& rgn) const {
|
||||
return size() == rgn.size() && committed_call_stack()->equals(*(rgn.reserved_call_stack()));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -194,15 +194,38 @@ class VirtualMemorySummary : AllStatic {
|
||||
*/
|
||||
class VirtualMemoryRegion {
|
||||
private:
|
||||
address _base_address;
|
||||
size_t _size;
|
||||
address _base_address;
|
||||
size_t _size;
|
||||
MemTag _mem_tag;
|
||||
NativeCallStack _reserved_stack;
|
||||
NativeCallStack _committed_stack;
|
||||
|
||||
public:
|
||||
VirtualMemoryRegion() :
|
||||
_base_address(nullptr), _size(0), _mem_tag(mtNone),
|
||||
_reserved_stack(NativeCallStack::empty_stack()) ,
|
||||
_committed_stack(NativeCallStack::empty_stack()) {}
|
||||
|
||||
VirtualMemoryRegion(address addr, size_t size) :
|
||||
_base_address(addr), _size(size) {
|
||||
_base_address(addr), _size(size), _mem_tag(mtNone),
|
||||
_reserved_stack(NativeCallStack::empty_stack()) ,
|
||||
_committed_stack(NativeCallStack::empty_stack()) {
|
||||
assert(addr != nullptr, "Invalid address");
|
||||
assert(size > 0, "Invalid size");
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMemoryRegion(address addr, size_t size, const NativeCallStack& reserved_stack, const NativeCallStack& committed_stack, MemTag mem_tag = mtNone) :
|
||||
_base_address(addr), _size(size), _mem_tag(mem_tag),
|
||||
_reserved_stack(reserved_stack),
|
||||
_committed_stack(committed_stack) {
|
||||
assert(addr != nullptr, "Invalid address");
|
||||
assert(size > 0, "Invalid size");
|
||||
}
|
||||
|
||||
VirtualMemoryRegion(address addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone)
|
||||
: _base_address(addr), _size(size), _mem_tag(mem_tag),
|
||||
_reserved_stack(stack),
|
||||
_committed_stack(NativeCallStack::empty_stack()) {}
|
||||
|
||||
inline address base() const { return _base_address; }
|
||||
inline address end() const { return base() + size(); }
|
||||
@ -211,48 +234,18 @@ class VirtualMemoryRegion {
|
||||
inline bool is_empty() const { return size() == 0; }
|
||||
|
||||
inline bool contain_address(address addr) const {
|
||||
assert(is_valid(), "sanity");
|
||||
return (addr >= base() && addr < end());
|
||||
}
|
||||
|
||||
|
||||
inline bool contain_region(address addr, size_t size) const {
|
||||
return contain_address(addr) && contain_address(addr + size - 1);
|
||||
}
|
||||
|
||||
inline bool same_region(address addr, size_t sz) const {
|
||||
return (addr == base() && sz == size());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
inline bool overlap_region(address addr, size_t sz) const {
|
||||
assert(sz > 0, "Invalid size");
|
||||
assert(size() > 0, "Invalid size");
|
||||
assert(is_valid(), "sanity");
|
||||
return MAX2(addr, base()) < MIN2(addr + sz, end());
|
||||
}
|
||||
|
||||
inline bool adjacent_to(address addr, size_t sz) const {
|
||||
return (addr == end() || (addr + sz) == base());
|
||||
}
|
||||
|
||||
void exclude_region(address addr, size_t sz) {
|
||||
assert(contain_region(addr, sz), "Not containment");
|
||||
assert(addr == base() || addr + sz == end(), "Can not exclude from middle");
|
||||
size_t new_size = size() - sz;
|
||||
|
||||
if (addr == base()) {
|
||||
set_base(addr + sz);
|
||||
}
|
||||
set_size(new_size);
|
||||
}
|
||||
|
||||
void expand_region(address addr, size_t sz) {
|
||||
assert(adjacent_to(addr, sz), "Not adjacent regions");
|
||||
if (base() == addr + sz) {
|
||||
set_base(addr);
|
||||
}
|
||||
set_size(size() + sz);
|
||||
}
|
||||
|
||||
// Returns 0 if regions overlap; 1 if this region follows rgn;
|
||||
// -1 if this region precedes rgn.
|
||||
inline int compare(const VirtualMemoryRegion& rgn) const {
|
||||
@ -266,86 +259,27 @@ class VirtualMemoryRegion {
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// Returns true if regions overlap, false otherwise.
|
||||
inline bool equals(const VirtualMemoryRegion& rgn) const {
|
||||
return compare(rgn) == 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
void set_base(address base) {
|
||||
assert(base != nullptr, "Sanity check");
|
||||
_base_address = base;
|
||||
}
|
||||
bool equals_including_stacks(const VirtualMemoryRegion& other) const;
|
||||
inline const NativeCallStack* committed_call_stack() const { return &_committed_stack; }
|
||||
|
||||
void set_size(size_t size) {
|
||||
assert(size > 0, "Sanity check");
|
||||
_size = size;
|
||||
}
|
||||
};
|
||||
bool is_valid() const { return base() != nullptr && size() != 0;}
|
||||
|
||||
inline const NativeCallStack* reserved_call_stack() const { return &_reserved_stack; }
|
||||
|
||||
class CommittedMemoryRegion : public VirtualMemoryRegion {
|
||||
private:
|
||||
NativeCallStack _stack;
|
||||
|
||||
public:
|
||||
CommittedMemoryRegion()
|
||||
: VirtualMemoryRegion((address)1, 1), _stack(NativeCallStack::empty_stack()) { }
|
||||
|
||||
CommittedMemoryRegion(address addr, size_t size, const NativeCallStack& stack)
|
||||
: VirtualMemoryRegion(addr, size), _stack(stack) { }
|
||||
|
||||
inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; }
|
||||
inline const NativeCallStack* call_stack() const { return &_stack; }
|
||||
bool equals(const ReservedMemoryRegion& other) const;
|
||||
};
|
||||
|
||||
class ReservedMemoryRegion : public VirtualMemoryRegion {
|
||||
private:
|
||||
NativeCallStack _stack;
|
||||
MemTag _mem_tag;
|
||||
|
||||
public:
|
||||
bool is_valid() { return base() != (address)1 && size() != 1;}
|
||||
|
||||
ReservedMemoryRegion()
|
||||
: VirtualMemoryRegion((address)1, 1), _stack(NativeCallStack::empty_stack()), _mem_tag(mtNone) { }
|
||||
|
||||
ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack,
|
||||
MemTag mem_tag = mtNone)
|
||||
: VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { }
|
||||
|
||||
|
||||
ReservedMemoryRegion(address base, size_t size)
|
||||
: VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _mem_tag(mtNone) { }
|
||||
|
||||
// Copy constructor
|
||||
ReservedMemoryRegion(const ReservedMemoryRegion& rr)
|
||||
: VirtualMemoryRegion(rr.base(), rr.size()) {
|
||||
*this = rr;
|
||||
}
|
||||
|
||||
inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; }
|
||||
inline const NativeCallStack* call_stack() const { return &_stack; }
|
||||
|
||||
inline MemTag mem_tag() const { return _mem_tag; }
|
||||
|
||||
ReservedMemoryRegion& operator= (const ReservedMemoryRegion& other) {
|
||||
set_base(other.base());
|
||||
set_size(other.size());
|
||||
|
||||
_stack = *other.call_stack();
|
||||
_mem_tag = other.mem_tag();
|
||||
|
||||
return *this;
|
||||
}
|
||||
inline MemTag mem_tag() const { return _mem_tag; }
|
||||
|
||||
const char* tag_name() const { return NMTUtil::tag_to_name(_mem_tag); }
|
||||
};
|
||||
|
||||
class VirtualMemoryWalker : public StackObj {
|
||||
public:
|
||||
virtual bool do_allocation_site(const ReservedMemoryRegion* rgn) { return false; }
|
||||
virtual bool do_allocation_site(const VirtualMemoryRegion* rgn) { return false; }
|
||||
};
|
||||
|
||||
|
||||
@ -376,8 +310,8 @@ class VirtualMemoryTracker {
|
||||
// Snapshot current thread stacks
|
||||
void snapshot_thread_stacks();
|
||||
void apply_summary_diff(VMATree::SummaryDiff diff);
|
||||
size_t committed_size(const ReservedMemoryRegion* rmr);
|
||||
address thread_stack_uncommitted_bottom(const ReservedMemoryRegion* rmr);
|
||||
size_t committed_size(const VirtualMemoryRegion* rgn);
|
||||
address thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn);
|
||||
|
||||
RegionsTree* tree() { return &_tree; }
|
||||
|
||||
@ -401,9 +335,9 @@ class VirtualMemoryTracker {
|
||||
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 ReservedMemoryRegion* rmr);
|
||||
static size_t committed_size(const VirtualMemoryRegion* rgn);
|
||||
// uncommitted thread stack bottom, above guard pages if there is any.
|
||||
static address thread_stack_uncommitted_bottom(const ReservedMemoryRegion* rmr);
|
||||
static address thread_stack_uncommitted_bottom(const VirtualMemoryRegion* rgn);
|
||||
|
||||
static RegionsTree* tree() { return _tracker->tree(); }
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -104,15 +104,15 @@ TEST_VM_F(NMTRegionsTreeTest, FindReservedRegion) {
|
||||
rt.reserve_mapping(1200, 50, rd, not_used);
|
||||
rt.reserve_mapping(1300, 50, rd, not_used);
|
||||
rt.reserve_mapping(1400, 50, rd, not_used);
|
||||
ReservedMemoryRegion rmr;
|
||||
rmr = rt.find_reserved_region((address)1205);
|
||||
EXPECT_EQ(rmr.base(), (address)1200);
|
||||
rmr = rt.find_reserved_region((address)1305);
|
||||
EXPECT_EQ(rmr.base(), (address)1300);
|
||||
rmr = rt.find_reserved_region((address)1405);
|
||||
EXPECT_EQ(rmr.base(), (address)1400);
|
||||
rmr = rt.find_reserved_region((address)1005);
|
||||
EXPECT_EQ(rmr.base(), (address)1000);
|
||||
VirtualMemoryRegion rgn;
|
||||
rgn = rt.find_reserved_region((address)1205);
|
||||
EXPECT_EQ(rgn.base(), (address)1200);
|
||||
rgn = rt.find_reserved_region((address)1305);
|
||||
EXPECT_EQ(rgn.base(), (address)1300);
|
||||
rgn = rt.find_reserved_region((address)1405);
|
||||
EXPECT_EQ(rgn.base(), (address)1400);
|
||||
rgn = rt.find_reserved_region((address)1005);
|
||||
EXPECT_EQ(rgn.base(), (address)1000);
|
||||
}
|
||||
|
||||
TEST_VM_F(NMTRegionsTreeTest, VisitReservedRegions) {
|
||||
@ -124,7 +124,7 @@ TEST_VM_F(NMTRegionsTreeTest, VisitReservedRegions) {
|
||||
rt.reserve_mapping(1300, 50, rd, not_used);
|
||||
rt.reserve_mapping(1400, 50, rd, not_used);
|
||||
|
||||
rt.visit_reserved_regions([&](const ReservedMemoryRegion& rgn) {
|
||||
rt.visit_reserved_regions([&](const VirtualMemoryRegion& rgn) {
|
||||
EXPECT_EQ(((size_t)rgn.base()) % 100, 0UL);
|
||||
EXPECT_EQ(rgn.size(), 50UL);
|
||||
return true;
|
||||
@ -144,9 +144,9 @@ TEST_VM_F(NMTRegionsTreeTest, VisitCommittedRegions) {
|
||||
rt.commit_region((address)1020, 5UL, ncs, not_used);
|
||||
rt.commit_region((address)1030, 5UL, ncs, not_used);
|
||||
rt.commit_region((address)1040, 5UL, ncs, not_used);
|
||||
ReservedMemoryRegion rmr((address)1000, 50);
|
||||
VirtualMemoryRegion rgn((address)1000, 50);
|
||||
size_t count = 0;
|
||||
rt.visit_committed_regions(rmr, [&](CommittedMemoryRegion& crgn) {
|
||||
rt.visit_committed_regions(rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
count++;
|
||||
EXPECT_EQ((((size_t)crgn.base()) % 100) / 10, count);
|
||||
EXPECT_EQ(crgn.size(), 5UL);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@ -45,15 +45,14 @@ public:
|
||||
VirtualMemoryTracker::Instance::snapshot_thread_stacks();
|
||||
}
|
||||
|
||||
ReservedMemoryRegion rmr_found;
|
||||
VirtualMemoryRegion rgn_found;
|
||||
{
|
||||
MemTracker::NmtVirtualMemoryLocker vml;
|
||||
rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region(stack_end);
|
||||
rgn_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region(stack_end);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(rmr_found.is_valid());
|
||||
ASSERT_EQ(rmr_found.base(), stack_end);
|
||||
|
||||
ASSERT_TRUE(rgn_found.is_valid());
|
||||
ASSERT_EQ(rgn_found.base(), stack_end);
|
||||
|
||||
int i = 0;
|
||||
address i_addr = (address)&i;
|
||||
@ -64,12 +63,12 @@ public:
|
||||
bool found_stack_top = false;
|
||||
{
|
||||
MemTracker::NmtVirtualMemoryLocker vml;
|
||||
VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr_found, [&](const CommittedMemoryRegion& cmr) {
|
||||
if (cmr.base() + cmr.size() == stack_top) {
|
||||
EXPECT_TRUE(cmr.size() <= stack_size);
|
||||
VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rgn_found, [&](const VirtualMemoryRegion& rgn) {
|
||||
if (rgn.base() + rgn.size() == stack_top) {
|
||||
EXPECT_TRUE(rgn.size() <= stack_size);
|
||||
found_stack_top = true;
|
||||
}
|
||||
if (i_addr < stack_top && i_addr >= cmr.base()) {
|
||||
if (i_addr < stack_top && i_addr >= rgn.base()) {
|
||||
found_i_addr = true;
|
||||
}
|
||||
i++;
|
||||
@ -115,25 +114,25 @@ public:
|
||||
}
|
||||
|
||||
// trigger the test
|
||||
ReservedMemoryRegion rmr_found;
|
||||
VirtualMemoryRegion rgn_found;
|
||||
{
|
||||
MemTracker::NmtVirtualMemoryLocker nvml;
|
||||
VirtualMemoryTracker::Instance::snapshot_thread_stacks();
|
||||
rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base);
|
||||
rgn_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base);
|
||||
}
|
||||
ASSERT_TRUE(rmr_found.is_valid());
|
||||
ASSERT_EQ(rmr_found.base(), (address)base);
|
||||
ASSERT_TRUE(rgn_found.is_valid());
|
||||
ASSERT_EQ(rgn_found.base(), (address)base);
|
||||
|
||||
|
||||
bool precise_tracking_supported = false;
|
||||
{
|
||||
MemTracker::NmtVirtualMemoryLocker nvml;
|
||||
VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr_found, [&](const CommittedMemoryRegion& cmr){
|
||||
if (cmr.size() == size) {
|
||||
VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rgn_found, [&](const VirtualMemoryRegion& rgn){
|
||||
if (rgn.size() == size) {
|
||||
return false;
|
||||
} else {
|
||||
precise_tracking_supported = true;
|
||||
check_covered_pages(cmr.base(), cmr.size(), (address)base, touch_pages, page_num);
|
||||
check_covered_pages(rgn.base(), rgn.size(), (address)base, touch_pages, page_num);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@ -151,9 +150,9 @@ public:
|
||||
{
|
||||
MemTracker::NmtVirtualMemoryLocker nvml;
|
||||
VirtualMemoryTracker::Instance::remove_released_region((address)base, size);
|
||||
rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base);
|
||||
rgn_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base);
|
||||
}
|
||||
ASSERT_TRUE(!rmr_found.is_valid());
|
||||
ASSERT_TRUE(!rgn_found.is_valid());
|
||||
}
|
||||
|
||||
static void test_committed_region() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@ -50,41 +50,41 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
#define check(vmt, rmr, regions) check_inner((vmt), (rmr), (regions), ARRAY_SIZE(regions), __FILE__, __LINE__)
|
||||
#define check(vmt, rgn, regions) check_inner((vmt), (rgn), (regions), ARRAY_SIZE(regions), __FILE__, __LINE__)
|
||||
|
||||
#define check_empty(vmt, rmr) \
|
||||
#define check_empty(vmt, rgn) \
|
||||
do { \
|
||||
check_inner((vmt), (rmr), nullptr, 0, __FILE__, __LINE__); \
|
||||
check_inner((vmt), (rgn), nullptr, 0, __FILE__, __LINE__); \
|
||||
} while (false)
|
||||
|
||||
static void diagnostic_print(VirtualMemoryTracker& vmt, const ReservedMemoryRegion& rmr) {
|
||||
LOG("In reserved region " PTR_FORMAT ", size %X:", p2i(rmr.base()), rmr.size());
|
||||
vmt.tree()->visit_committed_regions(rmr, [&](CommittedMemoryRegion& region) {
|
||||
LOG(" committed region: " PTR_FORMAT ", size %X", p2i(region.base()), region.size());
|
||||
static void diagnostic_print(VirtualMemoryTracker& vmt, const VirtualMemoryRegion& rgn) {
|
||||
LOG("In reserved region " PTR_FORMAT ", size %X:", p2i(rgn.base()), rgn.size());
|
||||
vmt.tree()->visit_committed_regions(rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
LOG(" committed region: " PTR_FORMAT ", size %X", p2i(crgn.base()), crgn.size());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
static void check_inner(VirtualMemoryTracker& vmt, const ReservedMemoryRegion& rmr, R* regions, size_t regions_size, const char* file, int line) {
|
||||
static void check_inner(VirtualMemoryTracker& vmt, const VirtualMemoryRegion& rgn, R* regions, size_t regions_size, const char* file, int line) {
|
||||
size_t i = 0;
|
||||
size_t size = 0;
|
||||
|
||||
// Helpful log
|
||||
diagnostic_print(vmt, rmr);
|
||||
diagnostic_print(vmt, rgn);
|
||||
|
||||
#define WHERE " from " << file << ":" << line
|
||||
|
||||
vmt.tree()->visit_committed_regions(rmr, [&](CommittedMemoryRegion& region) {
|
||||
vmt.tree()->visit_committed_regions(rgn, [&](VirtualMemoryRegion& crgn) {
|
||||
EXPECT_LT(i, regions_size) << WHERE;
|
||||
EXPECT_EQ(region.base(), regions[i]._addr) << WHERE;
|
||||
EXPECT_EQ(region.size(), regions[i]._size) << WHERE;
|
||||
size += region.size();
|
||||
EXPECT_EQ(crgn.base(), regions[i]._addr) << WHERE;
|
||||
EXPECT_EQ(crgn.size(), regions[i]._size) << WHERE;
|
||||
size += crgn.size();
|
||||
i++;
|
||||
return true;
|
||||
});
|
||||
|
||||
EXPECT_EQ(i, regions_size) << WHERE;
|
||||
EXPECT_EQ(size, vmt.committed_size(&rmr)) << WHERE;
|
||||
EXPECT_EQ(size, vmt.committed_size(&rgn)) << WHERE;
|
||||
}
|
||||
|
||||
class VirtualMemoryTrackerTest {
|
||||
@ -104,11 +104,11 @@ public:
|
||||
NativeCallStack stack(&frame1, 1);
|
||||
NativeCallStack stack2(&frame2, 1);
|
||||
|
||||
// Fetch the added RMR for the space
|
||||
ReservedMemoryRegion rmr = rtree->find_reserved_region(addr);
|
||||
// Fetch the added region for the space
|
||||
VirtualMemoryRegion rgn = rtree->find_reserved_region(addr);
|
||||
|
||||
ASSERT_EQ(rmr.size(), size);
|
||||
ASSERT_EQ(rmr.base(), addr);
|
||||
ASSERT_EQ(rgn.size(), size);
|
||||
ASSERT_EQ(rgn.base(), addr);
|
||||
|
||||
// Commit Size Granularity
|
||||
const size_t cs = 0x1000;
|
||||
@ -118,24 +118,24 @@ public:
|
||||
{ // Commit one region
|
||||
rtree->commit_region(addr + cs, cs, stack, diff);
|
||||
R r[] = { {addr + cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent - lower address
|
||||
rtree->commit_region(addr, cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent - higher address
|
||||
rtree->commit_region(addr + 2 * cs, cs, stack, diff);
|
||||
R r[] = { {addr, 3 * cs} };
|
||||
check(vmt,rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 0u);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 0u);
|
||||
|
||||
|
||||
// Commit adjacent regions with different stacks
|
||||
@ -143,14 +143,14 @@ public:
|
||||
{ // Commit one region
|
||||
rtree->commit_region(addr + cs, cs, stack, diff);
|
||||
R r[] = { {addr + cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent - lower address
|
||||
rtree->commit_region(addr, cs, stack2, diff);
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent - higher address
|
||||
@ -158,12 +158,12 @@ public:
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, cs},
|
||||
{addr + 2 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 0u);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 0u);
|
||||
}
|
||||
|
||||
static void test_add_committed_region_adjacent_overlapping() {
|
||||
@ -180,11 +180,11 @@ public:
|
||||
NativeCallStack stack(&frame1, 1);
|
||||
NativeCallStack stack2(&frame2, 1);
|
||||
|
||||
// Fetch the added RMR for the space
|
||||
ReservedMemoryRegion rmr = rtree->find_reserved_region(addr);
|
||||
// Fetch the added region for the space
|
||||
VirtualMemoryRegion rgn = rtree->find_reserved_region(addr);
|
||||
|
||||
ASSERT_EQ(rmr.size(), size);
|
||||
ASSERT_EQ(rmr.base(), addr);
|
||||
ASSERT_EQ(rgn.size(), size);
|
||||
ASSERT_EQ(rgn.base(), addr);
|
||||
|
||||
// Commit Size Granularity
|
||||
const size_t cs = 0x1000;
|
||||
@ -196,28 +196,28 @@ public:
|
||||
rtree->commit_region(addr + 3 * cs, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs},
|
||||
{addr + 3 * cs, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent and overlapping
|
||||
rtree->commit_region(addr + 2 * cs, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 5 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// revert to two non-adjacent regions
|
||||
rtree->uncommit_region(addr + 2 * cs, cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 4 * cs);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 4 * cs);
|
||||
|
||||
{ // Commit overlapping and adjacent
|
||||
rtree->commit_region(addr + cs, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 5 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
rtree->uncommit_region(addr, 5 * cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 0u);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 0u);
|
||||
|
||||
|
||||
// Commit adjacent and overlapping regions with different stacks
|
||||
@ -227,7 +227,7 @@ public:
|
||||
rtree->commit_region(addr + 3 * cs, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs},
|
||||
{addr + 3 * cs, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit adjacent and overlapping
|
||||
@ -235,20 +235,20 @@ public:
|
||||
R r[] = { {addr, 2 * cs},
|
||||
{addr + 2 * cs, 2 * cs},
|
||||
{addr + 4 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// revert to two non-adjacent regions
|
||||
rtree->commit_region(addr, 5 * cs, stack, diff);
|
||||
rtree->uncommit_region(addr + 2 * cs, cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 4 * cs);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 4 * cs);
|
||||
|
||||
{ // Commit overlapping and adjacent
|
||||
rtree->commit_region(addr + cs, 2 * cs, stack2, diff);
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, 2 * cs},
|
||||
{addr + 3 * cs, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
rtree->tree().remove_all();
|
||||
@ -269,12 +269,12 @@ public:
|
||||
NativeCallStack stack(&frame1, 1);
|
||||
NativeCallStack stack2(&frame2, 1);
|
||||
|
||||
// Fetch the added RMR for the space
|
||||
ReservedMemoryRegion rmr = rtree->find_reserved_region(addr);
|
||||
// Fetch the added region for the space
|
||||
VirtualMemoryRegion rgn = rtree->find_reserved_region(addr);
|
||||
|
||||
|
||||
ASSERT_EQ(rmr.size(), size);
|
||||
ASSERT_EQ(rmr.base(), addr);
|
||||
ASSERT_EQ(rgn.size(), size);
|
||||
ASSERT_EQ(rgn.base(), addr);
|
||||
|
||||
// Commit Size Granularity
|
||||
const size_t cs = 0x1000;
|
||||
@ -284,54 +284,54 @@ public:
|
||||
{ // Commit one region
|
||||
rtree->commit_region(addr, cs, stack, diff);
|
||||
R r[] = { {addr, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit the same region
|
||||
rtree->commit_region(addr, cs, stack, diff);
|
||||
R r[] = { {addr, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit a succeeding region
|
||||
rtree->commit_region(addr + cs, cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit over two regions
|
||||
rtree->commit_region(addr, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{// Commit first part of a region
|
||||
rtree->commit_region(addr, cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit second part of a region
|
||||
rtree->commit_region(addr + cs, cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit a third part
|
||||
rtree->commit_region(addr + 2 * cs, cs, stack, diff);
|
||||
R r[] = { {addr, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit in the middle of a region
|
||||
rtree->commit_region(addr + 1 * cs, cs, stack, diff);
|
||||
R r[] = { {addr, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 0u);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 0u);
|
||||
|
||||
// With preceding region
|
||||
|
||||
@ -342,71 +342,71 @@ public:
|
||||
{
|
||||
R r[] = { {addr, cs},
|
||||
{addr + 2 * cs, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
rtree->commit_region(addr + 3 * cs, cs, stack, diff);
|
||||
{
|
||||
R r[] = { {addr, cs},
|
||||
{addr + 2 * cs, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
rtree->commit_region(addr + 4 * cs, cs, stack, diff);
|
||||
{
|
||||
R r[] = { {addr, cs},
|
||||
{addr + 2 * cs, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
rtree->uncommit_region(addr, 5 * cs, diff);
|
||||
ASSERT_EQ(vmt.committed_size(&rmr), 0u);
|
||||
ASSERT_EQ(vmt.committed_size(&rgn), 0u);
|
||||
|
||||
// With different stacks
|
||||
|
||||
{ // Commit one region
|
||||
rtree->commit_region(addr, cs, stack, diff);
|
||||
R r[] = { {addr, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit the same region
|
||||
rtree->commit_region(addr, cs, stack2, diff);
|
||||
R r[] = { {addr, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit a succeeding region
|
||||
rtree->commit_region(addr + cs, cs, stack, diff);
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit over two regions
|
||||
rtree->commit_region(addr, 2 * cs, stack, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{// Commit first part of a region
|
||||
rtree->commit_region(addr, cs, stack2, diff);
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit second part of a region
|
||||
rtree->commit_region(addr + cs, cs, stack2, diff);
|
||||
R r[] = { {addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit a third part
|
||||
rtree->commit_region(addr + 2 * cs, cs, stack2, diff);
|
||||
R r[] = { {addr, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
{ // Commit in the middle of a region
|
||||
@ -414,7 +414,7 @@ public:
|
||||
R r[] = { {addr, cs},
|
||||
{addr + cs, cs},
|
||||
{addr + 2 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
rtree->tree().remove_all();
|
||||
@ -445,11 +445,11 @@ public:
|
||||
NativeCallStack stack(&frame1, 1);
|
||||
NativeCallStack stack2(&frame2, 1);
|
||||
|
||||
// Fetch the added RMR for the space
|
||||
ReservedMemoryRegion rmr = rtree->find_reserved_region(addr);
|
||||
// Fetch the added region for the space
|
||||
VirtualMemoryRegion rgn = rtree->find_reserved_region(addr);
|
||||
|
||||
ASSERT_EQ(rmr.size(), size);
|
||||
ASSERT_EQ(rmr.base(), addr);
|
||||
ASSERT_EQ(rgn.size(), size);
|
||||
ASSERT_EQ(rgn.base(), addr);
|
||||
|
||||
// Commit Size Granularity
|
||||
const size_t cs = 0x1000;
|
||||
@ -457,11 +457,11 @@ public:
|
||||
{ // Commit regions
|
||||
rtree->commit_region(addr, 3 * cs, stack, diff);
|
||||
R r[] = { {addr, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
// Remove only existing
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{
|
||||
@ -473,7 +473,7 @@ public:
|
||||
rtree->uncommit_region(addr, cs, diff);
|
||||
R r[] = { {addr + 2 * cs, cs},
|
||||
{addr + 4 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// add back
|
||||
@ -483,7 +483,7 @@ public:
|
||||
rtree->uncommit_region(addr + 2 * cs, cs, diff);
|
||||
R r[] = { {addr + 0 * cs, cs},
|
||||
{addr + 4 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
// add back
|
||||
@ -493,17 +493,17 @@ public:
|
||||
rtree->uncommit_region(addr + 4 * cs, cs, diff);
|
||||
R r[] = { {addr + 0 * cs, cs},
|
||||
{addr + 2 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
}
|
||||
|
||||
rtree->uncommit_region(addr, 5 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove larger region
|
||||
rtree->commit_region(addr + 1 * cs, cs, stack, diff);
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove smaller region - in the middle
|
||||
@ -511,50 +511,50 @@ public:
|
||||
rtree->uncommit_region(addr + 1 * cs, cs, diff);
|
||||
R r[] = { { addr + 0 * cs, cs},
|
||||
{ addr + 2 * cs, cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove smaller region - at the beginning
|
||||
rtree->commit_region(addr, 3 * cs, stack, diff);
|
||||
rtree->uncommit_region(addr + 0 * cs, cs, diff);
|
||||
R r[] = { { addr + 1 * cs, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove smaller region - at the end
|
||||
rtree->commit_region(addr, 3 * cs, stack, diff);
|
||||
rtree->uncommit_region(addr + 2 * cs, cs, diff);
|
||||
R r[] = { { addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove smaller, overlapping region - at the beginning
|
||||
rtree->commit_region(addr + 1 * cs, 4 * cs, stack, diff);
|
||||
rtree->uncommit_region(addr, 2 * cs, diff);
|
||||
R r[] = { { addr + 2 * cs, 3 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
rtree->uncommit_region(addr + 1 * cs, 4 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
{ // Remove smaller, overlapping region - at the end
|
||||
rtree->commit_region(addr, 3 * cs, stack, diff);
|
||||
rtree->uncommit_region(addr + 2 * cs, 2 * cs, diff);
|
||||
R r[] = { { addr, 2 * cs} };
|
||||
check(vmt, rmr, r);
|
||||
check(vmt, rgn, r);
|
||||
|
||||
rtree->uncommit_region(addr, 3 * cs, diff);
|
||||
check_empty(vmt, rmr);
|
||||
check_empty(vmt, rgn);
|
||||
}
|
||||
|
||||
rtree->tree().remove_all();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user