8233299: Implementation: JEP 365: ZGC on Windows
Reviewed-by: pliden, eosterlund
This commit is contained in:
parent
802580b236
commit
6ba58f7633
@ -347,7 +347,8 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
|
||||
# Only enable ZGC on supported platforms
|
||||
AC_MSG_CHECKING([if zgc can be built])
|
||||
if (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \
|
||||
(test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64") ||
|
||||
(test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64") || \
|
||||
(test "x$OPENJDK_TARGET_OS" = "xwindows" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \
|
||||
(test "x$OPENJDK_TARGET_OS" = "xmacosx" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"); then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
|
@ -517,8 +517,11 @@ private:
|
||||
// Sort by size, largest first
|
||||
_xmm_registers.sort(xmm_compare_register_size);
|
||||
|
||||
// On Windows, the caller reserves stack space for spilling register arguments
|
||||
const int arg_spill_size = frame::arg_reg_save_area_bytes;
|
||||
|
||||
// Stack pointer must be 16 bytes aligned for the call
|
||||
_spill_offset = _spill_size = align_up(xmm_spill_size + gp_spill_size, 16);
|
||||
_spill_offset = _spill_size = align_up(xmm_spill_size + gp_spill_size + arg_spill_size, 16);
|
||||
}
|
||||
|
||||
public:
|
||||
|
126
src/hotspot/os/windows/gc/z/zBackingFile_windows.cpp
Normal file
126
src/hotspot/os/windows/gc/z/zBackingFile_windows.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 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/zBackingFile_windows.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zGranuleMap.inline.hpp"
|
||||
#include "gc/z/zMapper_windows.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
// The backing file commits and uncommits physical memory, that can be
|
||||
// multi-mapped into the virtual address space. To support fine-graned
|
||||
// committing and uncommitting, each ZGranuleSize chunked is mapped to
|
||||
// a separate paging file mapping.
|
||||
|
||||
ZBackingFile::ZBackingFile() :
|
||||
_handles(MaxHeapSize),
|
||||
_size(0) {}
|
||||
|
||||
size_t ZBackingFile::size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
HANDLE ZBackingFile::get_handle(uintptr_t offset) const {
|
||||
HANDLE const handle = _handles.get(offset);
|
||||
assert(handle != 0, "Should be set");
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ZBackingFile::put_handle(uintptr_t offset, HANDLE handle) {
|
||||
assert(handle != INVALID_HANDLE_VALUE, "Invalid handle");
|
||||
assert(_handles.get(offset) == 0, "Should be cleared");
|
||||
_handles.put(offset, handle);
|
||||
}
|
||||
|
||||
void ZBackingFile::clear_handle(uintptr_t offset) {
|
||||
assert(_handles.get(offset) != 0, "Should be set");
|
||||
_handles.put(offset, 0);
|
||||
}
|
||||
|
||||
size_t ZBackingFile::commit_from_paging_file(size_t offset, size_t size) {
|
||||
for (size_t i = 0; i < size; i += ZGranuleSize) {
|
||||
HANDLE const handle = ZMapper::create_and_commit_paging_file_mapping(ZGranuleSize);
|
||||
if (handle == 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
put_handle(offset + i, handle);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t ZBackingFile::uncommit_from_paging_file(size_t offset, size_t size) {
|
||||
for (size_t i = 0; i < size; i += ZGranuleSize) {
|
||||
HANDLE const handle = get_handle(offset + i);
|
||||
clear_handle(offset + i);
|
||||
ZMapper::close_paging_file_mapping(handle);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t ZBackingFile::commit(size_t offset, size_t length) {
|
||||
log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
|
||||
offset / M, (offset + length) / M, length / M);
|
||||
|
||||
const size_t committed = commit_from_paging_file(offset, length);
|
||||
|
||||
const size_t end = offset + committed;
|
||||
if (end > _size) {
|
||||
// Update size
|
||||
_size = end;
|
||||
}
|
||||
|
||||
return committed;
|
||||
}
|
||||
|
||||
size_t ZBackingFile::uncommit(size_t offset, size_t length) {
|
||||
log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
|
||||
offset / M, (offset + length) / M, length / M);
|
||||
|
||||
return uncommit_from_paging_file(offset, length);
|
||||
}
|
||||
|
||||
void ZBackingFile::map(uintptr_t addr, size_t size, size_t offset) const {
|
||||
assert(is_aligned(offset, ZGranuleSize), "Misaligned");
|
||||
assert(is_aligned(addr, ZGranuleSize), "Misaligned");
|
||||
assert(is_aligned(size, ZGranuleSize), "Misaligned");
|
||||
|
||||
for (size_t i = 0; i < size; i += ZGranuleSize) {
|
||||
HANDLE const handle = get_handle(offset + i);
|
||||
ZMapper::map_view_replace_placeholder(handle, 0 /* offset */, addr + i, ZGranuleSize);
|
||||
}
|
||||
}
|
||||
|
||||
void ZBackingFile::unmap(uintptr_t addr, size_t size) const {
|
||||
assert(is_aligned(addr, ZGranuleSize), "Misaligned");
|
||||
assert(is_aligned(size, ZGranuleSize), "Misaligned");
|
||||
|
||||
for (size_t i = 0; i < size; i += ZGranuleSize) {
|
||||
ZMapper::unmap_view_preserve_placeholder(addr + i, ZGranuleSize);
|
||||
}
|
||||
}
|
56
src/hotspot/os/windows/gc/z/zBackingFile_windows.hpp
Normal file
56
src/hotspot/os/windows/gc/z/zBackingFile_windows.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP
|
||||
#define OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP
|
||||
|
||||
#include "gc/z/zGranuleMap.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class ZBackingFile {
|
||||
private:
|
||||
ZGranuleMap<HANDLE> _handles;
|
||||
size_t _size;
|
||||
|
||||
HANDLE get_handle(uintptr_t offset) const;
|
||||
void put_handle(uintptr_t offset, HANDLE handle);
|
||||
void clear_handle(uintptr_t offset);
|
||||
|
||||
size_t commit_from_paging_file(size_t offset, size_t size);
|
||||
size_t uncommit_from_paging_file(size_t offset, size_t size);
|
||||
|
||||
public:
|
||||
ZBackingFile();
|
||||
|
||||
size_t size() const;
|
||||
|
||||
size_t commit(size_t offset, size_t length);
|
||||
size_t uncommit(size_t offset, size_t length);
|
||||
|
||||
void map(uintptr_t addr, size_t size, size_t offset) const;
|
||||
void unmap(uintptr_t addr, size_t size) const;
|
||||
};
|
||||
|
||||
#endif // OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP
|
30
src/hotspot/os/windows/gc/z/zInitialize_windows.cpp
Normal file
30
src/hotspot/os/windows/gc/z/zInitialize_windows.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 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/zInitialize.hpp"
|
||||
#include "gc/z/zSyscall_windows.hpp"
|
||||
|
||||
void ZInitialize::initialize_os() {
|
||||
ZSyscall::initialize();
|
||||
}
|
29
src/hotspot/os/windows/gc/z/zLargePages_windows.cpp
Normal file
29
src/hotspot/os/windows/gc/z/zLargePages_windows.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 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/zLargePages.hpp"
|
||||
|
||||
void ZLargePages::initialize_platform() {
|
||||
_state = Disabled;
|
||||
}
|
254
src/hotspot/os/windows/gc/z/zMapper_windows.cpp
Normal file
254
src/hotspot/os/windows/gc/z/zMapper_windows.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 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/zMapper_windows.hpp"
|
||||
#include "gc/z/zSyscall_windows.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
// Memory reservation, commit, views, and placeholders.
|
||||
//
|
||||
// To be able to up-front reserve address space for the heap views, and later
|
||||
// multi-map the heap views to the same physical memory, without ever losing the
|
||||
// reservation of the reserved address space, we use "placeholders".
|
||||
//
|
||||
// These placeholders block out the address space from being used by other parts
|
||||
// of the process. To commit memory in this address space, the placeholder must
|
||||
// be replaced by anonymous memory, or replaced by mapping a view against a
|
||||
// paging file mapping. We use the later to support multi-mapping.
|
||||
//
|
||||
// We want to be able to dynamically commit and uncommit the physical memory of
|
||||
// the heap (and also unmap ZPages), in granules of ZGranuleSize bytes. There is
|
||||
// no way to grow and shrink the committed memory of a paging file mapping.
|
||||
// Therefore, we create multiple granule-sized page file mappings. The memory is
|
||||
// committed by creating a page file mapping, map a view against it, commit the
|
||||
// memory, unmap the view. The memory will stay committed until all views are
|
||||
// unmapped, and the paging file mapping handle is closed.
|
||||
//
|
||||
// When replacing a placeholder address space reservation with a mapped view
|
||||
// against a paging file mapping, the virtual address space must exactly match
|
||||
// an existing placeholder's address and size. Therefore we only deal with
|
||||
// granule-sized placeholders at this layer. Higher layers that keep track of
|
||||
// reserved available address space can (and will) coalesce placeholders, but
|
||||
// they will be split before being used.
|
||||
|
||||
#define fatal_error(msg, addr, size) \
|
||||
fatal(msg ": " PTR_FORMAT " " SIZE_FORMAT "M (%d)", \
|
||||
(addr), (size) / M, GetLastError())
|
||||
|
||||
uintptr_t ZMapper::reserve(uintptr_t addr, size_t size) {
|
||||
void* const res = ZSyscall::VirtualAlloc2(
|
||||
GetCurrentProcess(), // Process
|
||||
(void*)addr, // BaseAddress
|
||||
size, // Size
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, // AllocationType
|
||||
PAGE_NOACCESS, // PageProtection
|
||||
NULL, // ExtendedParameters
|
||||
0 // ParameterCount
|
||||
);
|
||||
|
||||
// Caller responsible for error handling
|
||||
return (uintptr_t)res;
|
||||
}
|
||||
|
||||
void ZMapper::unreserve(uintptr_t addr, size_t size) {
|
||||
const bool res = ZSyscall::VirtualFreeEx(
|
||||
GetCurrentProcess(), // hProcess
|
||||
(void*)addr, // lpAddress
|
||||
size, // dwSize
|
||||
MEM_RELEASE // dwFreeType
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal_error("Failed to unreserve memory", addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE ZMapper::create_paging_file_mapping(size_t size) {
|
||||
// Create mapping with SEC_RESERVE instead of SEC_COMMIT.
|
||||
//
|
||||
// We use MapViewOfFile3 for two different reasons:
|
||||
// 1) When commiting memory for the created paging file
|
||||
// 2) When mapping a view of the memory created in (2)
|
||||
//
|
||||
// The non-platform code is only setup to deal with out-of-memory
|
||||
// errors in (1). By using SEC_RESERVE, we prevent MapViewOfFile3
|
||||
// from failing because of "commit limit" checks. To actually commit
|
||||
// memory in (1), a call to VirtualAlloc2 is done.
|
||||
|
||||
HANDLE const res = ZSyscall::CreateFileMappingW(
|
||||
INVALID_HANDLE_VALUE, // hFile
|
||||
NULL, // lpFileMappingAttribute
|
||||
PAGE_READWRITE | SEC_RESERVE, // flProtect
|
||||
size >> 32, // dwMaximumSizeHigh
|
||||
size & 0xFFFFFFFF, // dwMaximumSizeLow
|
||||
NULL // lpName
|
||||
);
|
||||
|
||||
// Caller responsible for error handling
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ZMapper::commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size) {
|
||||
const uintptr_t addr = map_view_no_placeholder(file_handle, file_offset, size);
|
||||
if (addr == 0) {
|
||||
log_error(gc)("Failed to map view of paging file mapping (%d)", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const uintptr_t res = commit(addr, size);
|
||||
if (res != addr) {
|
||||
log_error(gc)("Failed to commit memory (%d)", GetLastError());
|
||||
}
|
||||
|
||||
unmap_view_no_placeholder(addr, size);
|
||||
|
||||
return res == addr;
|
||||
}
|
||||
|
||||
uintptr_t ZMapper::map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size) {
|
||||
void* const res = ZSyscall::MapViewOfFile3(
|
||||
file_handle, // FileMapping
|
||||
GetCurrentProcess(), // ProcessHandle
|
||||
NULL, // BaseAddress
|
||||
file_offset, // Offset
|
||||
size, // ViewSize
|
||||
0, // AllocationType
|
||||
PAGE_NOACCESS, // PageProtection
|
||||
NULL, // ExtendedParameters
|
||||
0 // ParameterCount
|
||||
);
|
||||
|
||||
// Caller responsible for error handling
|
||||
return (uintptr_t)res;
|
||||
}
|
||||
|
||||
void ZMapper::unmap_view_no_placeholder(uintptr_t addr, size_t size) {
|
||||
const bool res = ZSyscall::UnmapViewOfFile2(
|
||||
GetCurrentProcess(), // ProcessHandle
|
||||
(void*)addr, // BaseAddress
|
||||
0 // UnmapFlags
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal_error("Failed to unmap memory", addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t ZMapper::commit(uintptr_t addr, size_t size) {
|
||||
void* const res = ZSyscall::VirtualAlloc2(
|
||||
GetCurrentProcess(), // Process
|
||||
(void*)addr, // BaseAddress
|
||||
size, // Size
|
||||
MEM_COMMIT, // AllocationType
|
||||
PAGE_NOACCESS, // PageProtection
|
||||
NULL, // ExtendedParameters
|
||||
0 // ParameterCount
|
||||
);
|
||||
|
||||
// Caller responsible for error handling
|
||||
return (uintptr_t)res;
|
||||
}
|
||||
|
||||
HANDLE ZMapper::create_and_commit_paging_file_mapping(size_t size) {
|
||||
HANDLE const file_handle = create_paging_file_mapping(size);
|
||||
if (file_handle == 0) {
|
||||
log_error(gc)("Failed to create paging file mapping (%d)", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool res = commit_paging_file_mapping(file_handle, 0 /* file_offset */, size);
|
||||
if (!res) {
|
||||
close_paging_file_mapping(file_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file_handle;
|
||||
}
|
||||
|
||||
void ZMapper::close_paging_file_mapping(HANDLE file_handle) {
|
||||
const bool res = CloseHandle(
|
||||
file_handle // hObject
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal("Failed to close paging file handle (%d)", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
void ZMapper::split_placeholder(uintptr_t addr, size_t size) {
|
||||
const bool res = VirtualFree(
|
||||
(void*)addr, // lpAddress
|
||||
size, // dwSize
|
||||
MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER // dwFreeType
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal_error("Failed to split placeholder", addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void ZMapper::coalesce_placeholders(uintptr_t addr, size_t size) {
|
||||
const bool res = VirtualFree(
|
||||
(void*)addr, // lpAddress
|
||||
size, // dwSize
|
||||
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS // dwFreeType
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal_error("Failed to coalesce placeholders", addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void ZMapper::map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size) {
|
||||
void* const res = ZSyscall::MapViewOfFile3(
|
||||
file_handle, // FileMapping
|
||||
GetCurrentProcess(), // ProcessHandle
|
||||
(void*)addr, // BaseAddress
|
||||
file_offset, // Offset
|
||||
size, // ViewSize
|
||||
MEM_REPLACE_PLACEHOLDER, // AllocationType
|
||||
PAGE_READWRITE, // PageProtection
|
||||
NULL, // ExtendedParameters
|
||||
0 // ParameterCount
|
||||
);
|
||||
|
||||
if (res == NULL) {
|
||||
fatal_error("Failed to map memory", addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void ZMapper::unmap_view_preserve_placeholder(uintptr_t addr, size_t size) {
|
||||
const bool res = ZSyscall::UnmapViewOfFile2(
|
||||
GetCurrentProcess(), // ProcessHandle
|
||||
(void*)addr, // BaseAddress
|
||||
MEM_PRESERVE_PLACEHOLDER // UnmapFlags
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
fatal_error("Failed to unmap memory", addr, size);
|
||||
}
|
||||
}
|
85
src/hotspot/os/windows/gc/z/zMapper_windows.hpp
Normal file
85
src/hotspot/os/windows/gc/z/zMapper_windows.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP
|
||||
#define OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class ZMapper : public AllStatic {
|
||||
private:
|
||||
// Create paging file mapping
|
||||
static HANDLE create_paging_file_mapping(size_t size);
|
||||
|
||||
// Commit paging file mapping
|
||||
static bool commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size);
|
||||
|
||||
// Map a view anywhere without a placeholder
|
||||
static uintptr_t map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size);
|
||||
|
||||
// Unmap a view without preserving a placeholder
|
||||
static void unmap_view_no_placeholder(uintptr_t addr, size_t size);
|
||||
|
||||
// Commit memory covering the given virtual address range
|
||||
static uintptr_t commit(uintptr_t addr, size_t size);
|
||||
|
||||
public:
|
||||
// Reserve memory with a placeholder
|
||||
static uintptr_t reserve(uintptr_t addr, size_t size);
|
||||
|
||||
// Unreserve memory
|
||||
static void unreserve(uintptr_t addr, size_t size);
|
||||
|
||||
// Create and commit paging file mapping
|
||||
static HANDLE create_and_commit_paging_file_mapping(size_t size);
|
||||
|
||||
// Close paging file mapping
|
||||
static void close_paging_file_mapping(HANDLE file_handle);
|
||||
|
||||
// Split a placeholder
|
||||
//
|
||||
// A view can only replace an entire placeholder, so placeholders need to be
|
||||
// split and coalesced to be the exact size of the new views.
|
||||
// [addr, addr + size) needs to be a proper sub-placeholder of an existing
|
||||
// placeholder.
|
||||
static void split_placeholder(uintptr_t addr, size_t size);
|
||||
|
||||
// Coalesce a placeholder
|
||||
//
|
||||
// [addr, addr + size) is the new placeholder. A sub-placeholder needs to
|
||||
// exist within that range.
|
||||
static void coalesce_placeholders(uintptr_t addr, size_t size);
|
||||
|
||||
// Map a view of the file handle and replace the placeholder covering the
|
||||
// given virtual address range
|
||||
static void map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size);
|
||||
|
||||
// Unmap the view and reinstate a placeholder covering the given virtual
|
||||
// address range
|
||||
static void unmap_view_preserve_placeholder(uintptr_t addr, size_t size);
|
||||
};
|
||||
|
||||
#endif // OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP
|
42
src/hotspot/os/windows/gc/z/zNUMA_windows.cpp
Normal file
42
src/hotspot/os/windows/gc/z/zNUMA_windows.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 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/zNUMA.hpp"
|
||||
|
||||
void ZNUMA::initialize_platform() {
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
uint32_t ZNUMA::count() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t ZNUMA::id() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ZNUMA::memory_id(uintptr_t addr) {
|
||||
// NUMA support not enabled, assume everything belongs to node zero
|
||||
return 0;
|
||||
}
|
212
src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp
Normal file
212
src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 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/zLargePages.inline.hpp"
|
||||
#include "gc/z/zMapper_windows.hpp"
|
||||
#include "gc/z/zPhysicalMemory.inline.hpp"
|
||||
#include "gc/z/zPhysicalMemoryBacking_windows.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/init.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
bool ZPhysicalMemoryBacking::is_initialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
bool ZPhysicalMemoryBacking::supports_uncommit() {
|
||||
assert(!is_init_completed(), "Invalid state");
|
||||
assert(_file.size() >= ZGranuleSize, "Invalid size");
|
||||
|
||||
// Test if uncommit is supported by uncommitting and then re-committing a granule
|
||||
return commit(uncommit(ZGranuleSize)) == ZGranuleSize;
|
||||
}
|
||||
|
||||
size_t ZPhysicalMemoryBacking::commit(size_t size) {
|
||||
size_t committed = 0;
|
||||
|
||||
// Fill holes in the backing file
|
||||
while (committed < size) {
|
||||
size_t allocated = 0;
|
||||
const size_t remaining = size - committed;
|
||||
const uintptr_t start = _uncommitted.alloc_from_front_at_most(remaining, &allocated);
|
||||
if (start == UINTPTR_MAX) {
|
||||
// No holes to commit
|
||||
break;
|
||||
}
|
||||
|
||||
// Try commit hole
|
||||
const size_t filled = _file.commit(start, allocated);
|
||||
if (filled > 0) {
|
||||
// Successful or partialy successful
|
||||
_committed.free(start, filled);
|
||||
committed += filled;
|
||||
}
|
||||
if (filled < allocated) {
|
||||
// Failed or partialy failed
|
||||
_uncommitted.free(start + filled, allocated - filled);
|
||||
return committed;
|
||||
}
|
||||
}
|
||||
|
||||
// Expand backing file
|
||||
if (committed < size) {
|
||||
const size_t remaining = size - committed;
|
||||
const uintptr_t start = _file.size();
|
||||
const size_t expanded = _file.commit(start, remaining);
|
||||
if (expanded > 0) {
|
||||
// Successful or partialy successful
|
||||
_committed.free(start, expanded);
|
||||
committed += expanded;
|
||||
}
|
||||
}
|
||||
|
||||
return committed;
|
||||
}
|
||||
|
||||
size_t ZPhysicalMemoryBacking::uncommit(size_t size) {
|
||||
size_t uncommitted = 0;
|
||||
|
||||
// Punch holes in backing file
|
||||
while (uncommitted < size) {
|
||||
size_t allocated = 0;
|
||||
const size_t remaining = size - uncommitted;
|
||||
const uintptr_t start = _committed.alloc_from_back_at_most(remaining, &allocated);
|
||||
assert(start != UINTPTR_MAX, "Allocation should never fail");
|
||||
|
||||
// Try punch hole
|
||||
const size_t punched = _file.uncommit(start, allocated);
|
||||
if (punched > 0) {
|
||||
// Successful or partialy successful
|
||||
_uncommitted.free(start, punched);
|
||||
uncommitted += punched;
|
||||
}
|
||||
if (punched < allocated) {
|
||||
// Failed or partialy failed
|
||||
_committed.free(start + punched, allocated - punched);
|
||||
return uncommitted;
|
||||
}
|
||||
}
|
||||
|
||||
return uncommitted;
|
||||
}
|
||||
|
||||
ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) {
|
||||
assert(is_aligned(size, ZGranuleSize), "Invalid size");
|
||||
|
||||
ZPhysicalMemory pmem;
|
||||
|
||||
// Allocate segments
|
||||
for (size_t allocated = 0; allocated < size; allocated += ZGranuleSize) {
|
||||
const uintptr_t start = _committed.alloc_from_front(ZGranuleSize);
|
||||
assert(start != UINTPTR_MAX, "Allocation should never fail");
|
||||
pmem.add_segment(ZPhysicalMemorySegment(start, ZGranuleSize));
|
||||
}
|
||||
|
||||
return pmem;
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::free(const ZPhysicalMemory& pmem) {
|
||||
const size_t nsegments = pmem.nsegments();
|
||||
|
||||
// Free segments
|
||||
for (size_t i = 0; i < nsegments; i++) {
|
||||
const ZPhysicalMemorySegment& segment = pmem.segment(i);
|
||||
_committed.free(segment.start(), segment.size());
|
||||
}
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const {
|
||||
const size_t page_size = ZLargePages::is_explicit() ? os::large_page_size() : os::vm_page_size();
|
||||
os::pretouch_memory((void*)addr, (void*)(addr + size), page_size);
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const {
|
||||
const size_t nsegments = pmem.nsegments();
|
||||
size_t size = 0;
|
||||
|
||||
// Map segments
|
||||
for (size_t i = 0; i < nsegments; i++) {
|
||||
const ZPhysicalMemorySegment& segment = pmem.segment(i);
|
||||
_file.map(addr + size, segment.size(), segment.start());
|
||||
size += segment.size();
|
||||
}
|
||||
|
||||
// Pre-touch memory
|
||||
if (pretouch) {
|
||||
pretouch_view(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const {
|
||||
_file.unmap(addr, pmem.size());
|
||||
}
|
||||
|
||||
uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const {
|
||||
// From an NMT point of view we treat the first heap view (marked0) as committed
|
||||
return ZAddress::marked0(offset);
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
|
||||
if (ZVerifyViews) {
|
||||
// Map good view
|
||||
map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
|
||||
} else {
|
||||
// Map all views
|
||||
map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
|
||||
map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
|
||||
map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);
|
||||
}
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
|
||||
if (ZVerifyViews) {
|
||||
// Unmap good view
|
||||
unmap_view(pmem, ZAddress::good(offset));
|
||||
} else {
|
||||
// Unmap all views
|
||||
unmap_view(pmem, ZAddress::marked0(offset));
|
||||
unmap_view(pmem, ZAddress::marked1(offset));
|
||||
unmap_view(pmem, ZAddress::remapped(offset));
|
||||
}
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
|
||||
// Map good view
|
||||
assert(ZVerifyViews, "Should be enabled");
|
||||
map_view(pmem, ZAddress::good(offset), false /* pretouch */);
|
||||
}
|
||||
|
||||
void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
|
||||
// Unmap good view
|
||||
assert(ZVerifyViews, "Should be enabled");
|
||||
unmap_view(pmem, ZAddress::good(offset));
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP
|
||||
#define OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP
|
||||
|
||||
#include "gc/z/zBackingFile_windows.hpp"
|
||||
#include "gc/z/zMemory.hpp"
|
||||
|
||||
class ZPhysicalMemory;
|
||||
|
||||
class ZPhysicalMemoryBacking {
|
||||
private:
|
||||
ZBackingFile _file;
|
||||
ZMemoryManager _committed;
|
||||
ZMemoryManager _uncommitted;
|
||||
|
||||
void pretouch_view(uintptr_t addr, size_t size) const;
|
||||
void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const;
|
||||
void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const;
|
||||
|
||||
public:
|
||||
bool is_initialized() const;
|
||||
|
||||
void warn_commit_limits(size_t max) const;
|
||||
bool supports_uncommit();
|
||||
|
||||
size_t commit(size_t size);
|
||||
size_t uncommit(size_t size);
|
||||
|
||||
ZPhysicalMemory alloc(size_t size);
|
||||
void free(const ZPhysicalMemory& pmem);
|
||||
|
||||
uintptr_t nmt_address(uintptr_t offset) const;
|
||||
|
||||
void map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
|
||||
void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
|
||||
|
||||
void debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
|
||||
void debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
|
||||
};
|
||||
|
||||
#endif // OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP
|
58
src/hotspot/os/windows/gc/z/zSyscall_windows.cpp
Normal file
58
src/hotspot/os/windows/gc/z/zSyscall_windows.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 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/zSyscall_windows.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
ZSyscall::CreateFileMappingWFn ZSyscall::CreateFileMappingW;
|
||||
ZSyscall::VirtualAlloc2Fn ZSyscall::VirtualAlloc2;
|
||||
ZSyscall::VirtualFreeExFn ZSyscall::VirtualFreeEx;
|
||||
ZSyscall::MapViewOfFile3Fn ZSyscall::MapViewOfFile3;
|
||||
ZSyscall::UnmapViewOfFile2Fn ZSyscall::UnmapViewOfFile2;
|
||||
|
||||
template <typename Fn>
|
||||
static void lookup_symbol(Fn*& fn, const char* library, const char* symbol) {
|
||||
char ebuf[1024];
|
||||
void* const handle = os::dll_load(library, ebuf, sizeof(ebuf));
|
||||
if (handle == NULL) {
|
||||
log_error(gc)("Failed to load library: %s", library);
|
||||
vm_exit_during_initialization("ZGC requires Windows version 1803 or later");
|
||||
}
|
||||
|
||||
fn = reinterpret_cast<Fn*>(os::dll_lookup(handle, symbol));
|
||||
if (fn == NULL) {
|
||||
log_error(gc)("Failed to lookup symbol: %s", symbol);
|
||||
vm_exit_during_initialization("ZGC requires Windows version 1803 or later");
|
||||
}
|
||||
}
|
||||
|
||||
void ZSyscall::initialize() {
|
||||
lookup_symbol(CreateFileMappingW, "KernelBase", "CreateFileMappingW");
|
||||
lookup_symbol(VirtualAlloc2, "KernelBase", "VirtualAlloc2");
|
||||
lookup_symbol(VirtualFreeEx, "KernelBase", "VirtualFreeEx");
|
||||
lookup_symbol(MapViewOfFile3, "KernelBase", "MapViewOfFile3");
|
||||
lookup_symbol(UnmapViewOfFile2, "KernelBase", "UnmapViewOfFile2");
|
||||
}
|
50
src/hotspot/os/windows/gc/z/zSyscall_windows.hpp
Normal file
50
src/hotspot/os/windows/gc/z/zSyscall_windows.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP
|
||||
#define OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP
|
||||
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Memoryapi.h>
|
||||
|
||||
class ZSyscall {
|
||||
private:
|
||||
typedef HANDLE (*CreateFileMappingWFn)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCWSTR);
|
||||
typedef PVOID (*VirtualAlloc2Fn)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG);
|
||||
typedef BOOL (*VirtualFreeExFn)(HANDLE, LPVOID, SIZE_T, DWORD);
|
||||
typedef PVOID (*MapViewOfFile3Fn)(HANDLE, HANDLE, PVOID, ULONG64, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG);
|
||||
typedef BOOL (*UnmapViewOfFile2Fn)(HANDLE, PVOID, ULONG);
|
||||
|
||||
public:
|
||||
static CreateFileMappingWFn CreateFileMappingW;
|
||||
static VirtualAlloc2Fn VirtualAlloc2;
|
||||
static VirtualFreeExFn VirtualFreeEx;
|
||||
static MapViewOfFile3Fn MapViewOfFile3;
|
||||
static UnmapViewOfFile2Fn UnmapViewOfFile2;
|
||||
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
#endif // OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP
|
40
src/hotspot/os/windows/gc/z/zUtils_windows.cpp
Normal file
40
src/hotspot/os/windows/gc/z/zUtils_windows.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 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/zUtils.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
uintptr_t ZUtils::alloc_aligned(size_t alignment, size_t size) {
|
||||
void* const res = _aligned_malloc(size, alignment);
|
||||
|
||||
if (res == NULL) {
|
||||
fatal("_aligned_malloc failed");
|
||||
}
|
||||
|
||||
memset(res, 0, size);
|
||||
|
||||
return (uintptr_t)res;
|
||||
}
|
149
src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp
Normal file
149
src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 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/zMapper_windows.hpp"
|
||||
#include "gc/z/zVirtualMemory.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
static void split_placeholder(uintptr_t start, size_t size) {
|
||||
ZMapper::split_placeholder(ZAddress::marked0(start), size);
|
||||
ZMapper::split_placeholder(ZAddress::marked1(start), size);
|
||||
ZMapper::split_placeholder(ZAddress::remapped(start), size);
|
||||
}
|
||||
|
||||
static void coalesce_placeholders(uintptr_t start, size_t size) {
|
||||
ZMapper::coalesce_placeholders(ZAddress::marked0(start), size);
|
||||
ZMapper::coalesce_placeholders(ZAddress::marked1(start), size);
|
||||
ZMapper::coalesce_placeholders(ZAddress::remapped(start), size);
|
||||
}
|
||||
|
||||
static void split_into_placeholder_granules(uintptr_t start, size_t size) {
|
||||
for (uintptr_t addr = start; addr < start + size; addr += ZGranuleSize) {
|
||||
split_placeholder(addr, ZGranuleSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void coalesce_into_one_placeholder(uintptr_t start, size_t size) {
|
||||
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
|
||||
|
||||
if (size > ZGranuleSize) {
|
||||
coalesce_placeholders(start, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_callback(const ZMemory* area) {
|
||||
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
|
||||
coalesce_into_one_placeholder(area->start(), area->size());
|
||||
}
|
||||
|
||||
static void destroy_callback(const ZMemory* area) {
|
||||
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
|
||||
// Don't try split the last granule - VirtualFree will fail
|
||||
split_into_placeholder_granules(area->start(), area->size() - ZGranuleSize);
|
||||
}
|
||||
|
||||
static void shrink_from_front_callback(const ZMemory* area, size_t size) {
|
||||
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
|
||||
split_into_placeholder_granules(area->start(), size);
|
||||
}
|
||||
|
||||
static void shrink_from_back_callback(const ZMemory* area, size_t size) {
|
||||
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
|
||||
// Don't try split the last granule - VirtualFree will fail
|
||||
split_into_placeholder_granules(area->end() - size, size - ZGranuleSize);
|
||||
}
|
||||
|
||||
static void grow_from_front_callback(const ZMemory* area, size_t size) {
|
||||
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
|
||||
coalesce_into_one_placeholder(area->start() - size, area->size() + size);
|
||||
}
|
||||
|
||||
static void grow_from_back_callback(const ZMemory* area, size_t size) {
|
||||
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
|
||||
coalesce_into_one_placeholder(area->start(), area->size() + size);
|
||||
}
|
||||
|
||||
void ZVirtualMemoryManager::initialize_os() {
|
||||
// Each reserved virtual memory address area registered in _manager is
|
||||
// exactly covered by a single placeholder. Callbacks are installed so
|
||||
// that whenever a memory area changes, the corresponding placeholder
|
||||
// is adjusted.
|
||||
//
|
||||
// The create and grow callbacks are called when virtual memory is
|
||||
// returned to the memory manager. The new memory area is then covered
|
||||
// by a new single placeholder.
|
||||
//
|
||||
// The destroy and shrink callbacks are called when virtual memory is
|
||||
// allocated from the memory manager. The memory area is then is split
|
||||
// into granule-sized placeholders.
|
||||
//
|
||||
// See comment in zMapper_windows.cpp explaining why placeholders are
|
||||
// split into ZGranuleSize sized placeholders.
|
||||
|
||||
ZMemoryManager::Callbacks callbacks;
|
||||
|
||||
callbacks._create = &create_callback;
|
||||
callbacks._destroy = &destroy_callback;
|
||||
callbacks._shrink_from_front = &shrink_from_front_callback;
|
||||
callbacks._shrink_from_back = &shrink_from_back_callback;
|
||||
callbacks._grow_from_front = &grow_from_front_callback;
|
||||
callbacks._grow_from_back = &grow_from_back_callback;
|
||||
|
||||
_manager.register_callbacks(callbacks);
|
||||
}
|
||||
|
||||
bool ZVirtualMemoryManager::reserve_contiguous_platform(uintptr_t start, size_t size) {
|
||||
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
|
||||
|
||||
// Reserve address views
|
||||
const uintptr_t marked0 = ZAddress::marked0(start);
|
||||
const uintptr_t marked1 = ZAddress::marked1(start);
|
||||
const uintptr_t remapped = ZAddress::remapped(start);
|
||||
|
||||
// Reserve address space
|
||||
if (ZMapper::reserve(marked0, size) != marked0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ZMapper::reserve(marked1, size) != marked1) {
|
||||
ZMapper::unreserve(marked0, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ZMapper::reserve(remapped, size) != remapped) {
|
||||
ZMapper::unreserve(marked0, size);
|
||||
ZMapper::unreserve(marked1, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register address views with native memory tracker
|
||||
nmt_reserve(marked0, size);
|
||||
nmt_reserve(marked1, size);
|
||||
nmt_reserve(remapped, size);
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user