< prev index next >
src/hotspot/share/services/virtualMemoryTracker.cpp
Print this page
@@ -46,61 +46,96 @@
int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
return r1.compare(r2);
}
+static bool is_mergeable_with(CommittedMemoryRegion* rgn, address addr, size_t size, const NativeCallStack& stack) {
+ return rgn->adjacent_to(addr, size) && rgn->call_stack()->equals(stack);
+}
+
+static bool is_same_as(CommittedMemoryRegion* rgn, address addr, size_t size, const NativeCallStack& stack) {
+ // It would have made sense to use rgn->equals(...), but equals returns true for overlapping regions.
+ return rgn->same_region(addr, size) && rgn->call_stack()->equals(stack);
+}
+
+void ReservedMemoryRegion::merge_with(LinkedListNode<CommittedMemoryRegion>* node, address addr, size_t size, const NativeCallStack& stack) {
+ CommittedMemoryRegion* rgn = node->data();
+ assert(rgn->call_stack()->equals(stack), "Stack mismatch");
+ assert(rgn->adjacent_to(addr, size), "Not adjacent");
+
+ rgn->expand_region(addr, size);
+
+ LinkedListNode<CommittedMemoryRegion>* next = node->next();
+ if (next != NULL) {
+ address next_addr = next->data()->base();
+ size_t next_size = next->data()->size();
+ const NativeCallStack& next_stack = *next->data()->call_stack();
+
+ if (is_mergeable_with(rgn, next_addr, next_size, next_stack)) {
+ rgn->expand_region(next_addr, next_size);
+ _committed_regions.remove(next);
+ }
+ }
+}
+
bool ReservedMemoryRegion::add_committed_region(address addr, size_t size, const NativeCallStack& stack) {
assert(addr != NULL, "Invalid address");
assert(size > 0, "Invalid size");
assert(contain_region(addr, size), "Not contain this region");
- if (all_committed()) return true;
-
- CommittedMemoryRegion committed_rgn(addr, size, stack);
- LinkedListNode<CommittedMemoryRegion>* node = _committed_regions.head();
+ LinkedListNode<CommittedMemoryRegion>* prev = NULL;
- while (node != NULL) {
+ for (LinkedListNode<CommittedMemoryRegion>* node = _committed_regions.head();
+ node != NULL;
+ node = node->next()) {
CommittedMemoryRegion* rgn = node->data();
- if (rgn->same_region(addr, size)) {
- return true;
- }
- if (rgn->adjacent_to(addr, size)) {
- // special case to expand prior region if there is no next region
- LinkedListNode<CommittedMemoryRegion>* next = node->next();
- if (next == NULL && rgn->call_stack()->equals(stack)) {
- VirtualMemorySummary::record_uncommitted_memory(rgn->size(), flag());
- // the two adjacent regions have the same call stack, merge them
- rgn->expand_region(addr, size);
- VirtualMemorySummary::record_committed_memory(rgn->size(), flag());
+ // Ignore request if region already exists.
+ if (is_same_as(rgn, addr, size, stack)) {
return true;
}
- }
+ // Found an overlapping region
+ // - remove _all_ overlapping regions in preparation
+ // for the addition of this new region.
if (rgn->overlap_region(addr, size)) {
- // Clear a space for this region in the case it overlaps with any regions.
remove_uncommitted_region(addr, size);
- break; // commit below
+ break;
}
- if (rgn->end() >= addr + size){
+
+ // We searched past this new region.
+ if (rgn->base() >= addr + size) {
break;
}
- node = node->next();
+
+ prev = node;
}
- // New committed region
+ // At this point the previous overlapping regions have been
+ // cleared, and the full region guaranteed to be inserted.
VirtualMemorySummary::record_committed_memory(size, flag());
- return add_committed_region(committed_rgn);
+
+ // Try to merge if possible.
+
+ // Preceding node might be prev, or a node created by remove_uncommitted_region.
+ for (LinkedListNode<CommittedMemoryRegion>* node = (prev != NULL) ? prev : _committed_regions.head();
+ node != NULL;
+ node = node->next()) {
+ CommittedMemoryRegion* rgn = node->data();
+
+ if (is_mergeable_with(rgn, addr, size, stack)) {
+ merge_with(node, addr, size, stack);
+ return true;
}
-void ReservedMemoryRegion::set_all_committed(bool b) {
- if (all_committed() != b) {
- _all_committed = b;
- if (b) {
- VirtualMemorySummary::record_committed_memory(size(), flag());
+ if (rgn->base() >= addr + size) {
+ break;
}
}
+
+ // Couldn't merge with any regions - create a new region.
+ return add_committed_region(CommittedMemoryRegion(addr, size, stack));
}
bool ReservedMemoryRegion::remove_uncommitted_region(LinkedListNode<CommittedMemoryRegion>* node,
address addr, size_t size) {
assert(addr != NULL, "Invalid address");
@@ -133,49 +168,13 @@
return false;
}
bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) {
- // uncommit stack guard pages
- if (flag() == mtThreadStack && !same_region(addr, sz)) {
- return true;
- }
-
assert(addr != NULL, "Invalid address");
assert(sz > 0, "Invalid size");
- if (all_committed()) {
- assert(_committed_regions.is_empty(), "Sanity check");
- assert(contain_region(addr, sz), "Reserved region does not contain this region");
- set_all_committed(false);
- VirtualMemorySummary::record_uncommitted_memory(sz, flag());
- if (same_region(addr, sz)) {
- return true;
- } else {
- CommittedMemoryRegion rgn(base(), size(), *call_stack());
- if (rgn.base() == addr || rgn.end() == (addr + sz)) {
- rgn.exclude_region(addr, sz);
- return add_committed_region(rgn);
- } else {
- // split this region
- // top of the whole region
- address top =rgn.end();
- // use this region for lower part
- size_t exclude_size = rgn.end() - addr;
- rgn.exclude_region(addr, exclude_size);
- if (add_committed_region(rgn)) {
- // higher part
- address high_base = addr + sz;
- size_t high_size = top - high_base;
- CommittedMemoryRegion high_rgn(high_base, high_size, NativeCallStack::EMPTY_STACK);
- return add_committed_region(high_rgn);
- } else {
- return false;
- }
- }
- }
- } else {
CommittedMemoryRegion del_rgn(addr, sz, *call_stack());
address end = addr + sz;
LinkedListNode<CommittedMemoryRegion>* head = _committed_regions.head();
LinkedListNode<CommittedMemoryRegion>* prev = NULL;
@@ -221,11 +220,10 @@
}
prev = head;
head = head->next();
}
- }
return true;
}
void ReservedMemoryRegion::move_committed_regions(address addr, ReservedMemoryRegion& rgn) {
@@ -254,22 +252,18 @@
rgn._committed_regions.set_head(head);
}
size_t ReservedMemoryRegion::committed_size() const {
- if (all_committed()) {
- return size();
- } else {
size_t committed = 0;
LinkedListNode<CommittedMemoryRegion>* head =
_committed_regions.head();
while (head != NULL) {
committed += head->data()->size();
head = head->next();
}
return committed;
- }
}
void ReservedMemoryRegion::set_flag(MEMFLAGS f) {
assert((flag() == mtNone || flag() == f), "Overwrite memory type");
if (flag() != f) {
@@ -294,26 +288,20 @@
}
return true;
}
bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
- const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
+ const NativeCallStack& stack, MEMFLAGS flag) {
assert(base_addr != NULL, "Invalid address");
assert(size > 0, "Invalid size");
assert(_reserved_regions != NULL, "Sanity check");
ReservedMemoryRegion rgn(base_addr, size, stack, flag);
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
- LinkedListNode<ReservedMemoryRegion>* node;
+
if (reserved_rgn == NULL) {
VirtualMemorySummary::record_reserved_memory(size, flag);
- node = _reserved_regions->add(rgn);
- if (node != NULL) {
- node->data()->set_all_committed(all_committed);
- return true;
- } else {
- return false;
- }
+ return _reserved_regions->add(rgn) != NULL;
} else {
if (reserved_rgn->same_region(base_addr, size)) {
reserved_rgn->set_call_stack(stack);
reserved_rgn->set_flag(flag);
return true;
< prev index next >