/* * Copyright (c) 2015, 2019, 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 "precompiled.hpp" #include "gc/z/zAddress.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zVirtualMemory.inline.hpp" #include "logging/log.hpp" #include "services/memTracker.hpp" bool ZVirtualMemoryManager::reserve_range(uintptr_t start, size_t size) { // Reserve address space char* const marked0_addr = (char*)ZAddress::marked0(start); char* const marked1_addr = (char*)ZAddress::marked1(start); char* const remapped_addr = (char*)ZAddress::remapped(start); if (!os::attempt_reserve_memory_at(size, marked0_addr)) { return false; } if (!os::attempt_reserve_memory_at(size, marked1_addr)) { os::release_memory(marked0_addr, size); return false; } if (!os::attempt_reserve_memory_at(size, remapped_addr)) { os::release_memory(marked0_addr, size); os::release_memory(marked1_addr, size); return false; } // Make the address view free _manager.free(start, size); return true; } size_t ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) { if (reserve_range(start, size)) { return size; } if (size <= ZGranuleSize) { return 0; } const size_t range = size / 2; return reserve(start, range) + reserve(start + range, range); } ZVirtualMemoryManager::ZVirtualMemoryManager() : _manager(), _initialized(false) { log_info(gc, init)("Address Space: " PTR_FORMAT " - " PTR_FORMAT " (" SIZE_FORMAT "T)", ZAddressSpaceStart, ZAddressSpaceEnd, ZAddressSpaceSize / K / G); // Reserve address space if (reserve(0, ZAddressOffsetMax) < MaxHeapSize) { log_error(gc)("Failed to reserve enough address space for Java heap"); return; } // Successfully initialized _initialized = true; } bool ZVirtualMemoryManager::is_initialized() const { return _initialized; } ZVirtualMemory ZVirtualMemoryManager::alloc(size_t size, bool alloc_from_front) { uintptr_t start; if (alloc_from_front || size <= ZPageSizeSmall) { // Small page start = _manager.alloc_from_front(size); } else { // Medium/Large page start = _manager.alloc_from_back(size); } return ZVirtualMemory(start, size); } void ZVirtualMemoryManager::free(const ZVirtualMemory& vmem) { _manager.free(vmem.start(), vmem.size()); }