Path: blob/master/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp
40948 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "gc/z/zAddress.inline.hpp"25#include "gc/z/zGlobals.hpp"26#include "gc/z/zLargePages.inline.hpp"27#include "gc/z/zMapper_windows.hpp"28#include "gc/z/zSyscall_windows.hpp"29#include "gc/z/zVirtualMemory.hpp"30#include "utilities/align.hpp"31#include "utilities/debug.hpp"3233class ZVirtualMemoryManagerImpl : public CHeapObj<mtGC> {34public:35virtual void initialize_before_reserve() {}36virtual void initialize_after_reserve(ZMemoryManager* manager) {}37virtual bool reserve(uintptr_t addr, size_t size) = 0;38virtual void unreserve(uintptr_t addr, size_t size) = 0;39};4041// Implements small pages (paged) support using placeholder reservation.42class ZVirtualMemoryManagerSmallPages : public ZVirtualMemoryManagerImpl {43private:44class PlaceholderCallbacks : public AllStatic {45public:46static void split_placeholder(uintptr_t start, size_t size) {47ZMapper::split_placeholder(ZAddress::marked0(start), size);48ZMapper::split_placeholder(ZAddress::marked1(start), size);49ZMapper::split_placeholder(ZAddress::remapped(start), size);50}5152static void coalesce_placeholders(uintptr_t start, size_t size) {53ZMapper::coalesce_placeholders(ZAddress::marked0(start), size);54ZMapper::coalesce_placeholders(ZAddress::marked1(start), size);55ZMapper::coalesce_placeholders(ZAddress::remapped(start), size);56}5758static void split_into_placeholder_granules(uintptr_t start, size_t size) {59for (uintptr_t addr = start; addr < start + size; addr += ZGranuleSize) {60split_placeholder(addr, ZGranuleSize);61}62}6364static void coalesce_into_one_placeholder(uintptr_t start, size_t size) {65assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");6667if (size > ZGranuleSize) {68coalesce_placeholders(start, size);69}70}7172static void create_callback(const ZMemory* area) {73assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");74coalesce_into_one_placeholder(area->start(), area->size());75}7677static void destroy_callback(const ZMemory* area) {78assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");79// Don't try split the last granule - VirtualFree will fail80split_into_placeholder_granules(area->start(), area->size() - ZGranuleSize);81}8283static void shrink_from_front_callback(const ZMemory* area, size_t size) {84assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");85split_into_placeholder_granules(area->start(), size);86}8788static void shrink_from_back_callback(const ZMemory* area, size_t size) {89assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");90// Don't try split the last granule - VirtualFree will fail91split_into_placeholder_granules(area->end() - size, size - ZGranuleSize);92}9394static void grow_from_front_callback(const ZMemory* area, size_t size) {95assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");96coalesce_into_one_placeholder(area->start() - size, area->size() + size);97}9899static void grow_from_back_callback(const ZMemory* area, size_t size) {100assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");101coalesce_into_one_placeholder(area->start(), area->size() + size);102}103104static void register_with(ZMemoryManager* manager) {105// Each reserved virtual memory address area registered in _manager is106// exactly covered by a single placeholder. Callbacks are installed so107// that whenever a memory area changes, the corresponding placeholder108// is adjusted.109//110// The create and grow callbacks are called when virtual memory is111// returned to the memory manager. The new memory area is then covered112// by a new single placeholder.113//114// The destroy and shrink callbacks are called when virtual memory is115// allocated from the memory manager. The memory area is then is split116// into granule-sized placeholders.117//118// See comment in zMapper_windows.cpp explaining why placeholders are119// split into ZGranuleSize sized placeholders.120121ZMemoryManager::Callbacks callbacks;122123callbacks._create = &create_callback;124callbacks._destroy = &destroy_callback;125callbacks._shrink_from_front = &shrink_from_front_callback;126callbacks._shrink_from_back = &shrink_from_back_callback;127callbacks._grow_from_front = &grow_from_front_callback;128callbacks._grow_from_back = &grow_from_back_callback;129130manager->register_callbacks(callbacks);131}132};133134virtual void initialize_after_reserve(ZMemoryManager* manager) {135PlaceholderCallbacks::register_with(manager);136}137138virtual bool reserve(uintptr_t addr, size_t size) {139const uintptr_t res = ZMapper::reserve(addr, size);140141assert(res == addr || res == NULL, "Should not reserve other memory than requested");142return res == addr;143}144145virtual void unreserve(uintptr_t addr, size_t size) {146ZMapper::unreserve(addr, size);147}148};149150// Implements Large Pages (locked) support using shared AWE physical memory.151152// ZPhysicalMemory layer needs access to the section153HANDLE ZAWESection;154155class ZVirtualMemoryManagerLargePages : public ZVirtualMemoryManagerImpl {156private:157virtual void initialize_before_reserve() {158ZAWESection = ZMapper::create_shared_awe_section();159}160161virtual bool reserve(uintptr_t addr, size_t size) {162const uintptr_t res = ZMapper::reserve_for_shared_awe(ZAWESection, addr, size);163164assert(res == addr || res == NULL, "Should not reserve other memory than requested");165return res == addr;166}167168virtual void unreserve(uintptr_t addr, size_t size) {169ZMapper::unreserve_for_shared_awe(addr, size);170}171};172173static ZVirtualMemoryManagerImpl* _impl = NULL;174175void ZVirtualMemoryManager::pd_initialize_before_reserve() {176if (ZLargePages::is_enabled()) {177_impl = new ZVirtualMemoryManagerLargePages();178} else {179_impl = new ZVirtualMemoryManagerSmallPages();180}181_impl->initialize_before_reserve();182}183184void ZVirtualMemoryManager::pd_initialize_after_reserve() {185_impl->initialize_after_reserve(&_manager);186}187188bool ZVirtualMemoryManager::pd_reserve(uintptr_t addr, size_t size) {189return _impl->reserve(addr, size);190}191192void ZVirtualMemoryManager::pd_unreserve(uintptr_t addr, size_t size) {193_impl->unreserve(addr, size);194}195196197