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 { // we have to walk whole list to remove the committed regions in // specified range LinkedListNode<CommittedMemoryRegion>* head = _committed_regions.head(); LinkedListNode<CommittedMemoryRegion>* prev = NULL; VirtualMemoryRegion uncommitted_rgn(addr, sz); while (head != NULL && !uncommitted_rgn.is_empty()) { CommittedMemoryRegion* crgn = head->data(); // this committed region overlaps to region to uncommit if (crgn->overlap_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { if (crgn->same_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { // find matched region, remove the node will do VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); _committed_regions.remove_after(prev); return true; } else if (crgn->contain_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { // this committed region contains whole uncommitted region VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); return remove_uncommitted_region(head, uncommitted_rgn.base(), uncommitted_rgn.size()); } else if (uncommitted_rgn.contain_region(crgn->base(), crgn->size())) { // this committed region has been uncommitted size_t exclude_size = crgn->end() - uncommitted_rgn.base(); uncommitted_rgn.exclude_region(uncommitted_rgn.base(), exclude_size); VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); LinkedListNode<CommittedMemoryRegion>* tmp = head; head = head->next(); _committed_regions.remove_after(prev); continue; } else if (crgn->contain_address(uncommitted_rgn.base())) { size_t toUncommitted = crgn->end() - uncommitted_rgn.base(); crgn->exclude_region(uncommitted_rgn.base(), toUncommitted); uncommitted_rgn.exclude_region(uncommitted_rgn.base(), toUncommitted); VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); } else if (uncommitted_rgn.contain_address(crgn->base())) { size_t toUncommitted = uncommitted_rgn.end() - crgn->base(); crgn->exclude_region(crgn->base(), toUncommitted); uncommitted_rgn.exclude_region(uncommitted_rgn.end() - toUncommitted, toUncommitted); VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); } } prev = head; head = head->next(); } } return true; }
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; CommittedMemoryRegion* crgn; while (head != NULL) { crgn = head->data(); if (crgn->same_region(addr, sz)) { VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); _committed_regions.remove_after(prev); return true; } // del_rgn contains crgn if (del_rgn.contain_region(crgn->base(), crgn->size())) { VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); head = head->next(); _committed_regions.remove_after(prev); continue; // don't update head or prev } // Found addr in the current crgn. There are 2 subcases: if (crgn->contain_address(addr)) { // (1) Found addr+size in current crgn as well. (del_rgn is contained in crgn) if (crgn->contain_address(end - 1)) { VirtualMemorySummary::record_uncommitted_memory(sz, flag()); return remove_uncommitted_region(head, addr, sz); // done! } else { // (2) Did not find del_rgn's end in crgn. size_t size = crgn->end() - del_rgn.base(); crgn->exclude_region(addr, size); VirtualMemorySummary::record_uncommitted_memory(size, flag()); } } else if (crgn->contain_address(end - 1)) { // Found del_rgn's end, but not its base addr. size_t size = del_rgn.end() - crgn->base(); crgn->exclude_region(crgn->base(), size); VirtualMemorySummary::record_uncommitted_memory(size, flag()); return true; // should be done if the list is sorted properly! } prev = head; head = head->next(); } } return true; }